我有这个使用HTML Canvas创建线性渐变的Web工具。我想将这些渐变转换为有效的CSS渐变。我尝试了我所知道的关于数学的一切(不是很多)……没有任何实际结果。
我现在知道的事情: -CSS线性gradeint可以从负值开始,而Canvas渐变则不能。
这是我当前的工作:
var width = 50;
var height = 50;
var handlesPositions = [
{
"x": 0.16,
"y": -1.98
},
{
"x": 0.84,
"y": 2.98
},
]
var colorStops = [
{
"color": "#FF0000",
"position": 0.359
},
{
"color": "#0094FF",
"position": 0.495
},
{
"color": "#FFFF00",
"position": 0.652
}
];
// CANVAS
var c = document.getElementById("source");
var ctx = c.getContext("2d");
var x0 = handlesPositions[0].x * width;
var y0 = handlesPositions[0].y * height;
var x1 = handlesPositions[1].x * width;
var y1 = handlesPositions[1].y * height;
var grd = ctx.createLinearGradient(x0, y0, x1, y1);
grd.addColorStop(colorStops[0].position, colorStops[0].color);
grd.addColorStop(colorStops[1].position, colorStops[1].color);
grd.addColorStop(colorStops[2].position, colorStops[2].color);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 50, 50);
// CANVAS TO CSS
function canvasToLinearGradient(handles, stops) {
const handle0 = handles[0];
const handle1 = handles[1];
const ydiff = handle1.y - handle0.y;
const xdiff = handle0.x - handle1.x;
const angle = Math.atan2(-xdiff, -ydiff);
const cssStops = stops.map((stop) => {
return `${stop.color} ${Math.round(stop.position * 100)}%`;
}).join(', ');
return `linear-gradient(${angle}rad, ${cssStops})`;
}
document.getElementById("current").style.backgroundImage = canvasToLinearGradient(handlesPositions, colorStops);
#goal {
background: linear-gradient(172.19deg, #FF0000 -12.39%, #0094FF 48.06%, #FFFF00 117.89%);
}
.row {
display: flex;flex-direction:row;justify-content:space-between;align-items:center;margin-bottom:10px
}
<div style="width: 230px">
<div class="row">Goal <div id="goal" style="width:50px;height:50px;"></div></div>
<div class="row">Source <canvas id="source" width="50" height="50"></canvas></div>
<div class="row">Current result <div id="current" style="width:50px;height:50px;"></div>
</div>
答案 0 :(得分:1)
正如我在previous answer中所述,您可以尝试依靠background-size
/ background-position
来创建渐变。
首先,这是如何转换第一个渐变以使颜色介于0%
和100%
之间,并稍后使用Canvas轻松处理它的方法
#goal {
background: linear-gradient(172.19deg, #FF0000 -12.39%, #0094FF 48.06%, #FFFF00 117.89%);
}
#goal-1 {
/*we add 12.39% to all to make the first one 0%*/
background: linear-gradient(172.19deg, #FF0000 0%, #0094FF 60.45%, #FFFF00 130.29%);
}
#goal-2 {
/*we divide by 1.3029 all to make the last one 100%*/
background: linear-gradient(172.19deg, #FF0000 0%, #0094FF 46.39%, #FFFF00 100%);
}
#goal-3 {
/*we increase the size by 1.3029 to rectify the previous division*/
background: linear-gradient(172.19deg, #FF0000 0%, #0094FF 46.39%, #FFFF00 100%);
background-size:130.29% 130.29%;
}
#goal-4 {
/*we move the gradient to rectify the -12.39%*/
background: linear-gradient(172.19deg, #FF0000 0%, #0094FF 46.39%, #FFFF00 100%);
background-size:130.29% 130.29%;
background-position:calc((-0.1239 * 50px)/1.3029) calc((-0.1239 * 50px)/1.3029)
}
#goal-5 {
/*we can also wrote*/
background: linear-gradient(172.19deg, #FF0000 0%, #0094FF 46.39%, #FFFF00 100%) calc((-0.1239 * 50px)/1.3029) calc((-0.1239 * 50px)/1.3029)/ 130.29% 130.29%;}
.row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 10px
}
<div style="width: 230px">
<div class="row">Goal
<div id="goal" style="width:50px;height:50px;"></div>
</div>
<div class="row">Transition 1
<div id="goal-1" style="width:50px;height:50px;"></div>
</div>
<div class="row">Transition 2
<div id="goal-2" style="width:50px;height:50px;"></div>
</div>
<div class="row">Transition 3
<div id="goal-3" style="width:50px;height:50px;"></div>
</div>
<div class="row">Transition final
<div id="goal-4" style="width:50px;height:50px;"></div>
</div>
<div class="row">Transition final
<div id="goal-5" style="width:50px;height:50px;"></div>
</div>
</div>
现在,我们可以应用此逻辑来查找渐变。我们已经有了色标。现在我们需要正确找到渐变的大小,即两点之间的距离。然后找到背景位置。
这是我尝试添加背景尺寸的第一次尝试:
var width = 50;
var height = 50;
var handlesPositions = [
{
"x": 0.16,
"y": -1.98
},
{
"x": 0.84,
"y": 2.98
},
]
var colorStops = [
{
"color": "#FF0000",
"position": 0.359
},
{
"color": "#0094FF",
"position": 0.495
},
{
"color": "#FFFF00",
"position": 0.652
}
];
// CANVAS
var c = document.getElementById("source");
var ctx = c.getContext("2d");
var x0 = handlesPositions[0].x * width;
var y0 = handlesPositions[0].y * height;
var x1 = handlesPositions[1].x * width;
var y1 = handlesPositions[1].y * height;
var grd = ctx.createLinearGradient(x0, y0, x1, y1);
grd.addColorStop(colorStops[0].position, colorStops[0].color);
grd.addColorStop(colorStops[1].position, colorStops[1].color);
grd.addColorStop(colorStops[2].position, colorStops[2].color);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 50, 50);
// CANVAS TO CSS
function canvasToLinearGradient(handles, stops) {
const handle0 = handles[0];
const handle1 = handles[1];
const ydiff = handle1.y - handle0.y;
const xdiff = handle0.x - handle1.x;
const angle = Math.atan2(-xdiff, -ydiff);
const dist= Math.sqrt((y1-y0)*(y1-y0) + (x1-x0)*(x1-x0));
console.log(dist);
const cssStops = stops.map((stop) => {
return `${stop.color} ${stop.position * 100}%`;
}).join(', ');
return `linear-gradient(${angle}rad, ${cssStops}) 50% 50%/${dist}px ${dist}px`;
}
document.getElementById("current").style.background = canvasToLinearGradient(handlesPositions, colorStops);
#goal {
background: linear-gradient(172.19deg, #FF0000 -12.39%, #0094FF 48.06%, #FFFF00 117.89%);
}
.row {
display: flex;flex-direction:row;justify-content:space-between;align-items:center;margin-bottom:10px
}
<div style="width: 230px">
<div class="row">Goal <div id="goal" style="width:50px;height:50px;"></div></div>
<div class="row">Source <canvas id="source" width="50" height="50"></canvas></div>
<div class="row">Current result <div id="current" style="width:50px;height:50px;"></div>
</div>
如您所见,我们几乎很好。位置的计算有些棘手,将需要更多的深度说明。稍后将尝试对其进行编辑。