gpt4 book ai didi

javascript - HTML5 Canvas 围绕中心旋转渐变

转载 作者:行者123 更新时间:2023-11-30 21:16:36 24 4
gpt4 key购买 nike

我正在尝试围绕 Canvas 的中心点旋转渐变,但我没有运气找到实现此目的所需的正确计算。

我想做的一个例子是:http://victorblog.com/html5-canvas-gradient-creator/ .旋转 slider 正是我想要做的,但我查看了源代码,逻辑似乎可以使用 cos/sin 简化很多(尽管我不是这方面的专家,因此我为什么要问这个问题)。

我发现这个 SO 线程 ( Calculate rotation of canvas gradient ) 有点帮助,但它围绕中心点旋转,而不是像第一个示例中的旋转 slider 那样坚持它。

在此方面的任何帮助者将不胜感激。

谢谢

最佳答案

旋转渐变。


简单旋转。

如果您不担心渐变适合 Canvas ,那么简单的旋转即可解决问题。

首先你必须计算出渐变的最大长度,这样当它是对 Angular 线时它仍然适合 Canvas 。

const maxLength = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height);

然后你可以创建渐变如下

var angle = ?; // The angle in radians
// A value of 0 if a gradient from right to left
const gradient = ctx.createLinearGradient(
// the start of the gradient added to the center
canvas.width / 2 + Math.cos(angle) * maxLength * 0.5,
canvas.height / 2 + Math.sin(angle) * maxLength * 0.5,
// the end of the gradient subtracted from the center
canvas.width / 2 - Math.cos(angle) * maxLength * 0.5,
canvas.height / 2 - Math.sin(angle) * maxLength * 0.5
)

这可行,但当渐变不沿对 Angular 线时会裁剪渐变。

拟合对 Angular 线示例

const eachOf=(a,cb)=>{var i=0;const len=a.length;while(i<len)cb(a[i], i++);};
const ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
const maxWidth = Math.sqrt(w * w + h * h) / 2;
// empty colour items are skipped when creating the gradient
const gradientColours = ["white","blue",,,,"green","yellow","green",,,,"cyan","black"];
function createRotatedGradient(angle, colors){
const g = ctx.createLinearGradient(
w / 2 + Math.cos(angle) * maxWidth, // start pos
h / 2 + Math.sin(angle) * maxWidth,
w / 2 - Math.cos(angle) * maxWidth, // end pos
h / 2 - Math.sin(angle) * maxWidth
);
// add colours
eachOf(colors,(col,i)=> col && g.addColorStop(i / (colors.length - 1), col) );
return g;
}

function update(timer){
ctx.fillStyle = createRotatedGradient(timer / 1000,gradientColours);
ctx.fillRect(0,0,w,h);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas><

这可以通过设置 maxWidth 来修改以适应宽度或高度。 canvas.height 的梯度或 canvas.width

适合高度示例

const eachOf=(a,cb)=>{var i=0;const len=a.length;while(i<len)cb(a[i], i++);};
const ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
const maxWidth = h / 2;
// empty colour items are skipped when creating the gradient
const gradientColours = ["white","green",,,,"blue","cyan","blue",,,,"yellow","black"];
function createRotatedGradient(angle, colors){
const g = ctx.createLinearGradient(
w / 2 + Math.cos(angle) * maxWidth, // start pos
h / 2 + Math.sin(angle) * maxWidth,
w / 2 - Math.cos(angle) * maxWidth, // end pos
h / 2 - Math.sin(angle) * maxWidth
);
// add colours
eachOf(colors,(col,i)=> col && g.addColorStop(i / (colors.length - 1), col) );
return g;
}

function update(timer){
ctx.fillStyle = createRotatedGradient(timer / 1000,gradientColours);
ctx.fillRect(0,0,w,h);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas><

适合宽度示例

const eachOf=(a,cb)=>{var i=0;const len=a.length;while(i<len)cb(a[i], i++);};
const ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
const maxWidth = w / 2;
// empty colour items are skipped when creating the gradient
const gradientColours = ["white","blue",,,,"yellow","green","yellow",,,,"cyan","black"];
function createRotatedGradient(angle, colors){
const g = ctx.createLinearGradient(
w / 2 + Math.cos(angle) * maxWidth, // start pos
h / 2 + Math.sin(angle) * maxWidth,
w / 2 - Math.cos(angle) * maxWidth, // end pos
h / 2 - Math.sin(angle) * maxWidth
);
// add colours
eachOf(colors,(col,i)=> col && g.addColorStop(i / (colors.length - 1), col) );
return g;
}

function update(timer){
ctx.fillStyle = createRotatedGradient(timer / 1000,gradientColours);
ctx.fillRect(0,0,w,h);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas><


简单的动态拟合

要适应宽度和高度,您可以使用非常简单的 y 轴缩放。这个比例是宽度和高度的比例。

const maxLen = canvas.width;
const aspect = canvas.height / canvas.width;
const angle = ?
const gradient = ctx.createLinearGradient(
// the start of the gradient added to the center
canvas.width / 2 + Math.cos(angle) * maxLen * 0.5,
canvas.height / 2 + Math.sin(angle) * maxLen * 0.5 * aspect,
// the end of the gradient subtracted from the center
canvas.width / 2 - Math.cos(angle) * maxLen * 0.5,
canvas.height / 2 - Math.sin(angle) * maxLen * 0.5 * aspect
)

纵横比缩放示例

const eachOf=(a,cb)=>{var i=0;const len=a.length;while(i<len)cb(a[i], i++);};
const ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
const maxWidth = w / 2;
const aspect = h / w;
// empty colour items are skipped when creating the gradient
const gradientColours = ["white","red",,,,"yellow","green","yellow",,,,"red","black"];
function createRotatedGradient(angle, colors){
const g = ctx.createLinearGradient(
w / 2 + Math.cos(angle) * maxWidth, // start pos
h / 2 + Math.sin(angle) * maxWidth * aspect,
w / 2 - Math.cos(angle) * maxWidth, // end pos
h / 2 - Math.sin(angle) * maxWidth * aspect
);
// add colours
eachOf(colors,(col,i)=> col && g.addColorStop(i / (colors.length - 1), col) );
return g;
}

function update(timer){
ctx.fillStyle = createRotatedGradient(timer / 1000,gradientColours);
ctx.fillRect(0,0,w,h);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas><


最适合。

example site您提供了拟合梯度,使其来自最近的边缘,这是一个更好的拟合,但仍然不是完美的拟合,因为梯度有时会太短。由于您从该站点获得了方法,因此我不会在此处包含它。

最佳适配稍微复杂一些,但始终适合 Canvas ,因此 Canvas 不会溢出或欠流(不会从渐变外部设置像素,并且所有渐变在任何 Angular 都可见)

有关信息,请参阅示例。数学取自并改编自 this answer适合旋转图像。

最佳匹配示例。

const eachOf=(a,cb)=>{var i=0;const len=a.length;while(i<len)cb(a[i], i++);};
const ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
const maxWidth = w / 2;
const aspect = h / w;
// empty colour items are skipped when creating the gradient
const gradientColours = ["black","white",,,,"white","red",,,,,,,,,"yellow","green","yellow",,,,,,,,,"red","black",,,,"black","white"];

function bestFitGradient(angle, colors){

var dist = Math.sqrt(w * w + h * h) / 2; // get the diagonal length
var diagAngle = Math.asin((h / 2) / dist); // get the diagonal angle

// Do the symmetry on the angle (move to first quad
var a1 = ((angle % (Math.PI *2))+ Math.PI*4) % (Math.PI * 2);
if(a1 > Math.PI){ a1 -= Math.PI }
if(a1 > Math.PI / 2 && a1 <= Math.PI){ a1 = (Math.PI / 2) - (a1 - (Math.PI / 2)) }
// get angles from center to edges for along and right of gradient
var ang1 = Math.PI/2 - diagAngle - Math.abs(a1);
var ang2 = Math.abs(diagAngle - Math.abs(a1));

// get distance from center to horizontal and vertical edges
var dist1 = Math.cos(ang1) * h;
var dist2 = Math.cos(ang2) * w;

// get the max distance
var scale = Math.max(dist2, dist1) / 2;

// get the vector to the start and end of gradient
var dx = Math.cos(angle) * scale;
var dy = Math.sin(angle) * scale;

// create the gradient
const g = ctx.createLinearGradient(
w / 2 + dx, // start pos
h / 2 + dy,
w / 2 - dx, // end pos
h / 2 - dy
);
// add colours
eachOf(colors,(col,i)=> col && g.addColorStop(i / (colors.length - 1), col) );
return g;
}



function update(timer){
ctx.fillStyle = bestFitGradient(timer / 1000,gradientColours);
ctx.fillRect(0,0,w,h);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas><

关于javascript - HTML5 Canvas 围绕中心旋转渐变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45624502/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com