Reputation: 13
I've created a canvas pattern and want to repeat the pattern diagonally through the whole web page. Since the repeat property only support repeat-x, repeat-y or repeat both direction, I've set it to 'no-repeat' for now and tried to use offset or translate to move my pattern diagonally, but didn't work out.
Here is what I got for now:
Here is what I want to accomplish: enter image description here
I'm just trying to mimic the effect, doesn't need to be exact the same.
Can someone tell me how to continue my pattern diagonally? Thanks a lot!
Here are some of my codes:
var patternCanvas = document.createElement('canvas');
var patternContext = patternCanvas.getContext('2d');
patternCanvas.width = 350;
patternCanvas.height = 350;
patternContext.fillStyle = "orange";
patternContext.fillRect(0, 50, 150, 50);
patternContext.fillRect(50, 0, 50, 150);
patternContext.fillStyle = "black";
patternContext.fillRect(100, 100, 150, 50);
patternContext.fillRect(150, 50, 50, 150);
patternContext.fillStyle = "green";
patternContext.fillRect(200, 150, 150, 50);
patternContext.fillRect(250, 100, 50, 150);
patternContext.fillStyle = "darkred";
patternContext.fillRect(0, 100, 50, 150);
patternContext.fillRect(0, 150, 150, 50);
patternContext.fillStyle = "blue";
patternContext.fillRect(100, 150, 50, 150);
patternContext.fillRect(50, 200, 150, 50);
patternContext.fillStyle = "yellow";
patternContext.fillRect(200, 200, 50, 150);
patternContext.fillRect(150, 250, 150, 50);
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var context = canvas.getContext('2d');
var pattern = context.createPattern(patternCanvas, 'no-repeat');
context.fillStyle = pattern;
context.fillRect(0, 0, 350, 350);
<canvas id="myCanvas"></canvas>
Upvotes: 1
Views: 591
Reputation: 4246
This solution treats the canvas as a blank slate rather than as a place to copy/paste a pattern.
It creates the appearance of a repeating pattern by dividing the canvas into squares and coloring each square according to its position in a virtual grid.
Thanks to irchans for help with the math.
const
// Creates a canvas, and a context
canvas = document.getElementById("myCanvas"),
context = canvas.getContext('2d'),
// Configures colors, unit-square size, and the number of unit squares to draw
colors = "blue,yellow,darkred,green,orange,black".split(","),
unit = 50,
gridDimensionX = 10,
gridDimensionY = 10;
// Makes the canvas wide enough for its content
canvas.width = unit * gridDimensionX;
canvas.height = unit * gridDimensionY;
// Builds a grid of squares, each of which is assigned a color
const grid = makeGrid(gridDimensionX, gridDimensionY, colors);
// Loops through the grid and draws each square
drawGrid(grid, context, unit);
// Defines the `makeGrid` function
function makeGrid(gridDimensionX, gridDimensionY, colors){
const grid = [];
for(let y = 0; y < gridDimensionY; y++){
const row = [];
for(let x = 0; x < gridDimensionX; x++){
// Assigns coordinates to each not-yet-drawn square, along two axes
// (rotated 60 degrees from the vertical and horizontal axes)
// and groups squares according to these coordinates
cell = {
slantyRowGrp: Math.round((2 * y - x) / 5, 0),
slantyColGrp: Math.round((y + 2 * x) / 5, 0)
}
// Assigns a color to each square based on its 'slanty' grouping
cell.colorIndex = (cell.slantyRowGrp + 2 * cell.slantyColGrp) % colors.length;
cell.color = colors[cell.colorIndex];
// Adds the cell to the row
row.push(cell);
}
// Adds the completed row to the grid
grid.push(row);
}
// Returns the completed grid
return grid;
}
// Defines the `drawGrid` function
function drawGrid(grid, context, unit){
grid.forEach( (row, y) => {
row.forEach( (cell, x) => {
// Fills each square with its assigned color
context.fillStyle = cell.color;
context.fillRect(unit * x, unit * y, unit, unit);
// Displays the 'slanty' row and column group numbers
/*
context.fillStyle = "lightgrey";
context.fillText(
`${cell.slantyRowGrp}; ${cell.slantyColGrp}`,
unit * x + unit/2.5,
unit * y + unit/2
);
*/
});
});
}
<canvas id="myCanvas"></canvas>
Upvotes: 1
Reputation: 2422
It took quite a lot of effort to achieve. It's a deceptively complex question.
Each position moves by something like x = x + (iterationY/3) * 2
, y = iterationX
although my code has denormalized iteration steps for ix
and iy
of 1/3, to make it easier to reason about moving by cross blocks e.g. 1/3 width or height of a cross.
To assign an id to each cross for colouring, I take a row and column where x/y iterations have a step of 1 as row = iterationX % 2
and col = iterationY % 3
, which gives row going from 0, 1 and so on, and col going from 0, 1, 2 and repeating. In this case I assign col a weight of 2, so the id = row+(col*2)
, to ensure each id is unique. Finally, I define an array of colours which can be referenced by this id.
const canvas = document.getElementById("canv");
const ctx = canvas.getContext('2d');
const w = window.innerWidth;
const h = window.innerHeight;
const s = 80;//size
const bs = s / 3;//block size
const gs = Math.max(w, h)/s;//grid size
canvas.width = w;
canvas.height = h;
let yAcc = 0;
let jx = 0;
let jy = 0;
const getColour = (jx, jy) => {
const row = (jx%2);//0, 1
const col = (jy % 3);//0, 1, 2
//00, 10, 01, 11, 02, 12
//0 , 1 , 2 , 3 , 4 , 5
const id = row + (col*2);
const colours = ['orange', 'blue', 'black', 'yellow', 'green', 'red']
return colours[id];
}
for(let ix = 0; ix < gs; ix+=1/3){
for(let iy = 0; iy < gs; iy+=1/3){
const colour = getColour(jx, jy);
let x = ix+iy*2-(gs);
let y = iy+ix*3-(gs);
ctx.fillStyle = colour;
ctx.beginPath();
ctx.lineWidth = 2;
ctx.rect(x * bs * 3, y * bs * 3 + bs, bs * 3, bs);
ctx.rect(x * bs * 3 + bs, y * bs * 3, bs, bs * 3);
ctx.fill();
ctx.closePath();
jy ++;
}
jx ++;
}
<canvas id="canv"></canvas>
Upvotes: 1