我需要在画布上绘制。

问题描述 投票:0回答:2
如果使用transform方法,我可以在Canvas上绘制渐变:

const canvas = document.getElementById('canvasBuiltInScale'); const ctx = canvas.getContext('2d'); function draw(x0, y0, x1, y1) { ctx.save(); // create a square 1x1 gradient const gradient = ctx.createLinearGradient(0, 0, 1, 1); gradient.addColorStop(0.4, 'yellow'); gradient.addColorStop(0.5, 'black'); gradient.addColorStop(0.6, 'red'); // scale it up to the size of the bbox const width = x1 - x0; const height = y1 - y0; ctx.transform(width, 0, 0, height, x0, y0); ctx.fillStyle = gradient; ctx.fillRect(0, 0, 1, 1); ctx.restore(); } draw(10, 10, 40, 30);

但是很不幸,客户不希望我使用transform方法。

我可以用原点缩放比例在画布上绘制相同的渐变。

const canvas = document.getElementById('canvasHomeRolledScale'); const ctx = canvas.getContext('2d'); function draw(x0, y0, x1, y1) { const width = x1-x0; const height = y1-y0; // The problem is that with userSpace coordinates, the normal to the gradient vector from x0,y0 to x1,y1 will not go between x1,y0 and x0,y1 // I perform a home baked geometric calculation to find the normal vector to [x1-x0, y1-y0] since its normal vector will pass through [x1-x0, y1-y0] const gradient = ctx.createLinearGradient( x0 + (width - height) / 2, y0 + (height - width) / 2, x0 + (width - height) / 2 + height, y0 + (height - width) / 2 + width ); gradient.addColorStop(rescale(0.4), 'yellow'); gradient.addColorStop(rescale(0.5), 'black'); gradient.addColorStop(rescale(0.6), 'red'); ctx.fillStyle = gradient; ctx.fillRect(x0, y0, width, height); // The normal vector calculated above has the right direction, but not the right amplitude. // Here I guy guessed that I could use pythagoras theorem to arrive at the correct scale function rescale(percent) { const max = Math.max(height, width) const min = Math.min(height, width) const f = ( Math.sqrt( Math.pow(max, 2) + Math.pow(min, 2) ) / Math.sqrt( Math.pow(max, 2) + Math.pow(max, 2) ) ); const midPoint = 0.5; return midPoint - (midPoint-percent) * f } } draw(10, 10, 40, 30);

但是我不允许更改色标的百分比。

两种情况下的反对意见都是有效的反对意见,应该对此问题有一个更简单,更优雅的解决方案。因此,我问这里的聪明人是否有解决方案:

不使用变换方法

不更改色标[这是具有使用objectBoundingBox渐变单位的线性渐变的SVG:

  • ]]

svg canvas transform linear-algebra coordinate-transformation
2个回答
1
投票

<canvas id=canvas width=100 height=100></canvas> <script> function svgimage() { var image = ` <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" version="1.1"> <defs> <linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox"> <stop offset="40%" stop-color="yellow" /> <stop offset="50%" stop-color="black" /> <stop offset="60%" stop-color="red" /> </linearGradient> </defs> <rect x="0" y="0" width="100" height="100" fill="url('#myGradient')" /> </svg>`; return encodeURIComponent(image); } function drawImage() { ctx.drawImage(img, 0, 0); } var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); var img = new Image(); img.onload = drawImage img.src = 'data:image/svg+xml;charset=utf-8,' + svgimage(); </script>


0
投票

const canvas = document.getElementById('canvasBuiltInScale'); const ctx = canvas.getContext('2d'); function tcoord(x0, y0, x1, y1){ let xc = (x1 + x0) / 2; let yc = (y1 + y0) / 2; let dx = (x1 - x0) / 2; let dy = (y1 - y0) / 2; let rx0 = xc - dy; let ry0 = yc - dx; let rx1 = xc + dy; let ry1 = yc + dx; let result = [rx0,ry0,rx1,ry1]; return result; } function draw(x0, y0, x1, y1) { ctx.save(); let c = tcoord(x0, y0, x0 + x1, y0 + y1); const gradient = ctx.createLinearGradient(c[0], c[1], c[2], c[3]); gradient.addColorStop(0.4, 'yellow'); gradient.addColorStop(0.5, 'black'); gradient.addColorStop(0.6, 'red'); ctx.fillStyle = gradient; ctx.fillRect(x0, y0, x1, y1); ctx.restore(); } draw(10, 10, 80, 60);

<canvas id="canvasBuiltInScale" width="300" height="300"> </canvas>

对于它的价值,我发现您的transform解决方案更优雅。
© www.soinside.com 2019 - 2024. All rights reserved.