背景の中で何種類かのパターンを繰り返して表示する
背景の中で何種類かのパターンを繰り返して表示する
全然書かなくなるということになったので、たまたま業務でやったやつを残しておく。
表題がめちゃくちゃわかりにくいけど、要はこんな感じのやつ。
例えば500 * 1000のパターンを4種類繰り返して表示するみたいなこと。
実装
CSSではできないのでcanvas
を背面に敷きましょう。
HTML & CSS
<div class="wrapper" id="js-wrapper"> <canvas id="c"></canvas> <div class="contents"> ここに内容を書く </div> </div>
.wrapper { position: relative } canvas { position: absolute; top: 0; left: 0 } .contents { position: relative }
そういうわけでcanvasです。
const c = document.getElementById('c'); const ctx = c.getContext('2d'); const PATTERN_HEIGHT = 1000; let w; let h; // 描画のサイズが知りたいので親要素も取得する。 const wrapper = document.getElementById('js-wrapper'); const init = () => { w = c.width = wrapper.offsetWidth; h = c.height = wrapper.offsetHeight; } init(); // パターン画像の種類 const PATTERN_1 = 'PATTERN_1'; const PATTERN_2 = 'PATTERN_2'; const PATTERN_3 = 'PATTERN_3'; // パターンのサイズを柔軟にしたいのでpatternObj.imgにはimgではなくcanvasを格納する const patternSource = [ { name: PATTERN_1, url: '/assets/img/pattern_1.png', img: document.createElement('canvas') }, { name: PATTERN_2, url: '/assets/img/pattern_2.png', img: document.createElement('canvas') }, { name: PATTERN_3, url: '/assets/img/pattern_3.png', img: document.createElement('canvas') }, ]; // パターンの順番 const patternOrder = [ PATTERN_2, PATTERN_3, PATTERN_2, PATTERN_1, ]; // イメージをロードする const loadImage = patternObj => new Promise(resolve => { const img = new Image(); img.src = patternObj.url; img.onload = () => { // canvasにimgを任意のサイズで描画する。 const imgWidth = patternObj.img.width = img.width; const imgHeight = patternObj.img.height = img.height; const imgCtx = patternObj.img.getContext('2d'); imgCtx.drawImage(img, 0, 0, imgWidth, imgHeight); resolve() } }); // imageリソースを全て取得してからコールバックを実行 const loadImages = async (patternSource, callback) => { await Promise.all( patternSource.map( pattern => loadImage(pattern) ) ) callback(); }; const drawPattern = ( ctx, startX, startY, width, height, maxY, patternSource, patternOrder ) => { let i = 0; let drawHeight = startY; while(drawHeight < maxY) { const source = patternSource.filter(source => source.name === patternOrder[i % patternOrder.length])[0].img; const pattern = ctx.createPattern(source, 'repeat'); ctx.fillStyle = pattern; ctx.fillRect(startX, startY + height * i, width, height); i++; drawHeight += height; } } const draw = () => { init(); ctx.clearRect(0, 0, w, h); // 左右ハーフステップで繰り返させる drawPattern( ctx, 0, 0, w / 2, PATTERN_HEIGHT, h, patternSource, patternOrder ) drawPattern( ctx, w / 2, -PATTERN_HEIGHT / 2, w / 2, PATTERN_HEIGHT, h, patternSource, patternOrder ) } ctx.beginPath() loadImages(patternSource, draw)
だるい
はい。