-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from devshareacademy/canvas-nine-slice
Canvas nine slice demo
- Loading branch information
Showing
11 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"recommendations": ["esbenp.prettier-vscode", "ritwickdey.LiveServer"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"eslint.format.enable": true, | ||
"editor.defaultFormatter": "esbenp.prettier-vscode", | ||
"[javascript]": { | ||
"editor.defaultFormatter": "esbenp.prettier-vscode" | ||
}, | ||
"prettier.singleQuote": true, | ||
"prettier.semi": true, | ||
"editor.formatOnSave": true, | ||
"cSpell.words": ["bdragon", "kenneys", "tileset"], | ||
"prettier.printWidth": 120 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Canvas API - Nine Slice Demo | ||
|
||
![demo](docs/example.gif) | ||
|
||
A quick demo of how you can use the nine slice scaling technique with the Canvas API when drawing your images to the HTML `<canvas>` element. | ||
|
||
For a detailed walkthrough, checkout my video on YouTube here: | ||
|
||
[<img src="https://i.ytimg.com/vi/PJM8isAuDoI/hqdefault.jpg">](https://youtu.be/PJM8isAuDoI 'How to Draw, Scale, and Slice Images using the Canvas API') | ||
|
||
Link to live demo: | ||
|
||
[Demo](https://devshareacademy.github.io/code-examples-from-my-video-content/canavs-api/nine-slice-example/index.html) | ||
|
||
## Credit | ||
|
||
The images used in this demo were created by: | ||
|
||
- [bdragon1727](https://bdragon1727.itch.io/border-and-panels-menu-part-1) | ||
- [kenney](https://www.kenney.nl/assets/ui-pack-space-expansion) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
https://bdragon1727.itch.io/border-and-panels-menu-part-1 |
Binary file added
BIN
+636 Bytes
...-api/nine-slice-example/assets/kenneys-assets/ui-space-expansion/glassPanel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions
14
canavs-api/nine-slice-example/assets/kenneys-assets/ui-space-expansion/license.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
############################################################################### | ||
|
||
UI pack: Space extension by Kenney Vleugels (www.kenney.nl) | ||
|
||
------------------------------ | ||
|
||
License (CC0) | ||
http://creativecommons.org/publicdomain/zero/1.0/ | ||
|
||
You may use these graphics in personal and commercial projects. | ||
Credit (Kenney or www.kenney.nl) would be nice but is not mandatory. | ||
|
||
############################################################################### |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Canvas API - Nine Slice Example</title> | ||
<style> | ||
html, | ||
body, | ||
.container { | ||
margin: 0px; | ||
height: 100vh; | ||
width: 100vw; | ||
overflow: hidden; | ||
background: #d7d7d7; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
canvas { | ||
background: #000000; | ||
box-shadow: 15px 15px 10px -5px rgba(0, 0, 0, 0.2); | ||
image-rendering: pixelated; | ||
zoom: 2; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container" id="game-container"> | ||
<canvas id="game" width="400" height="300"></canvas> | ||
</div> | ||
<script type="module" src="src/main.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "es6", | ||
"target": "es6", | ||
"checkJs": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/** | ||
* @typedef SubRectangle | ||
* @type {[number, number, number, number]} | ||
*/ | ||
|
||
/** | ||
* @param {string} src | ||
* @returns {Promise<HTMLImageElement>} | ||
*/ | ||
function loadImage(src) { | ||
return new Promise((resolve) => { | ||
const img = new Image(); | ||
img.addEventListener( | ||
'load', | ||
() => { | ||
resolve(img); | ||
}, | ||
false | ||
); | ||
img.src = src; | ||
}); | ||
} | ||
|
||
/* | ||
A B | ||
+---+----------------------+---+ | ||
C | 1 | 2 | 3 | | ||
+---+----------------------+---+ | ||
| | | | | ||
| 4 | 5 | 6 | | ||
| | | | | ||
+---+----------------------+---+ | ||
D | 7 | 8 | 9 | | ||
+---+----------------------+---+ | ||
areas 1, 3, 7 and 9 (the corners) will remain unscaled | ||
areas 2 and 8 will be stretched horizontally only | ||
areas 4 and 6 will be stretched vertically only | ||
area 5 will be stretched both horizontally and vertically | ||
*/ | ||
|
||
/** | ||
* | ||
* @param {CanvasRenderingContext2D} ctx | ||
* @param {HTMLImageElement} img | ||
* @param {number} leftWidth | ||
* @param {number} rightWidth | ||
* @param {number} topHeight | ||
* @param {number} bottomHeight | ||
* @param {number} x | ||
* @param {number} y | ||
* @param {number} width | ||
* @param {number} height | ||
* @returns {void} | ||
*/ | ||
function drawNineSliceImage(ctx, img, leftWidth, rightWidth, topHeight, bottomHeight, x, y, width, height) { | ||
const totalWidthCut = leftWidth + rightWidth; | ||
const totalHeightCut = topHeight + bottomHeight; | ||
// break the main image up into 9 parts, based on the size of the slice. | ||
// each piece should be [x, y, width, height] | ||
|
||
// start in the top left corner for our first cut | ||
/** @type {SubRectangle} */ | ||
const topLeft = [0, 0, leftWidth, topHeight]; | ||
// for the middle, we need to calculate the width remaining after we take our two cuts | ||
/** @type {SubRectangle} */ | ||
const topMiddle = [leftWidth, 0, img.width - totalWidthCut, topHeight]; | ||
// for the top right side corner we just need to take the total width and remove the cut length | ||
/** @type {SubRectangle} */ | ||
const topRight = [img.width - rightWidth, 0, rightWidth, topHeight]; | ||
|
||
// for the middle left, we take the overall image height and subtract the size of the two corner cuts to get new height | ||
const middleRowHeight = img.height - totalHeightCut; | ||
/** @type {SubRectangle} */ | ||
const middleLeft = [0, topHeight, leftWidth, middleRowHeight]; | ||
// for the middle, we need to take the overall image height and width, subtract the two corner cuts to get the new dimensions | ||
/** @type {SubRectangle} */ | ||
const center = [leftWidth, topHeight, img.width - totalWidthCut, middleRowHeight]; | ||
// for the middle right, we need to do similar logic that was done for the middle left piece | ||
/** @type {SubRectangle} */ | ||
const middleRight = [img.width - rightWidth, topHeight, rightWidth, middleRowHeight]; | ||
|
||
// for the bottom left, we take the overall image height and subtract the corner cut | ||
const bottomRowY = img.height - bottomHeight; | ||
/** @type {SubRectangle} */ | ||
const bottomLeft = [0, bottomRowY, leftWidth, bottomHeight]; | ||
// for the bottom middle, we do the same logic we did in the top middle frame, just at a lower y value | ||
/** @type {SubRectangle} */ | ||
const bottomMiddle = [leftWidth, bottomRowY, img.width - totalWidthCut, bottomHeight]; | ||
// for the bottom right, we do the same logic we did in the top right frame, just at a lower y value | ||
/** @type {SubRectangle} */ | ||
const bottomRight = [img.width - rightWidth, bottomRowY, rightWidth, bottomHeight]; | ||
|
||
// now that we have our nine sub rectangles that make up the original source image, we can draw those onto the canvas element | ||
// drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) Note: the sx, sy, sWidth, and sHeight where already calculated above | ||
|
||
// draw the top row | ||
ctx.drawImage(img, ...topLeft, x, y, leftWidth, topHeight); | ||
ctx.drawImage(img, ...topMiddle, x + leftWidth, y, width - totalWidthCut, topHeight); | ||
ctx.drawImage(img, ...topRight, x + width - rightWidth, y, rightWidth, topHeight); | ||
// draw the middle row | ||
ctx.drawImage(img, ...middleLeft, x, y + topHeight, leftWidth, height - totalHeightCut); | ||
ctx.drawImage(img, ...center, x + leftWidth, y + topHeight, width - totalWidthCut, height - totalHeightCut); | ||
ctx.drawImage(img, ...middleRight, x + width - rightWidth, y + topHeight, rightWidth, height - totalHeightCut); | ||
// draw the bottom row | ||
ctx.drawImage(img, ...bottomLeft, x, y + height - bottomHeight, leftWidth, bottomHeight); | ||
ctx.drawImage(img, ...bottomMiddle, x + leftWidth, y + height - bottomHeight, width - totalWidthCut, bottomHeight); | ||
ctx.drawImage(img, ...bottomRight, x + width - rightWidth, y + height - bottomHeight, rightWidth, bottomHeight); | ||
} | ||
|
||
void (async function () { | ||
const canvas = document.getElementById('game'); | ||
if (!(canvas instanceof HTMLCanvasElement)) { | ||
console.log('HTMLCanvasElement not found'); | ||
return; | ||
} | ||
const ctx = canvas.getContext('2d'); | ||
if (!(ctx instanceof CanvasRenderingContext2D)) { | ||
console.log('CanvasRenderingContext2D not found'); | ||
return; | ||
} | ||
|
||
const img = await loadImage('assets/bdragon1727/border.png'); | ||
// const img = await loadImage('assets/kenneys-assets/ui-space-expansion/glassPanel.png'); | ||
|
||
// // example of drawing image directly | ||
// ctx.drawImage(img, 0, 0); | ||
// // example of scaling by providing width and height on destination | ||
// ctx.drawImage(img, 0, 0, img.width * 1.5, img.height * 1.5); | ||
//ctx.drawImage(img, 25, 25, 350, 250); | ||
|
||
// example of using nine slice technique to scale image | ||
drawNineSliceImage(ctx, img, 32, 32, 32, 32, 25, 25, 350, 250); | ||
})(); |