围绕多边形绘制渐变斜面
Draw gradient bevel around polygon
基本上我需要为给定的多边形创建衰减纹理。例如这是我的图像
我需要创建的是这个,但是从白色到黑色的斜角渐变,将绿色部分视为渐变。
我得到了所有顶点的坐标和斜面的厚度。我正在使用 HTML5 2d canvas 进行渲染。基本上最明显的解决方案是计算每个像素到多边形的距离,如果它在厚度参数内,则计算颜色并为像素着色。但这是繁重的计算,而且会很慢,即使对于满足我需要的尽可能小的纹理也是如此。那么我可以用 canvas 来实现这个目标吗?
只需以不同的笔画宽度绘制多边形的轮廓,并根据宽度的每一步改变颜色。
该片段展示了一种实现方法。使用线连接 "miter" 和 "round"
绘制 2 个多边形
"use strict";
const canvas = document.createElement("canvas");
canvas.height = innerHeight;
canvas.width = innerWidth;
canvas.style.position = "absolute";
canvas.style.top = canvas.style.left = "0px";
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
// poly to draw
var poly = [0.1,0.2,0.4,0.5,0.2,0.8];
var poly1 = [0.6,0.1,0.9,0.5,0.8,0.9];
// convert rgb style colour to array
function rgb2Array(rgb){
var arr1 = rgb.split("(")[1].split(")")[0].split(",");
var arr = [];
while(arr1.length > 0){
arr.push(Number(arr1.shift()));
}
return arr;
}
// convert array to rgb colour
function array2rgb(arr){
return "rgb("+Math.floor(arr[0])+","+Math.floor(arr[1])+","+Math.floor(arr[2])+")"
}
// lerps array from to. Amount is from 0 @ from 1 @ to. res = is the resulting array
function lerpArr(from,to,amount,res){
var i = 0;
if(res === undefined){
res = [];
}
while(i < from.length){
res[i] = (to[i]-from[i]) * amount + from[i];
i++;
}
return res;
}
// draw gradient outline
// poly is the polygon verts
// width is the outline width
// fillStyle is the polygon fill style
// rgb1 is the outer colour
// rgb2 is the inner colour of the outline gradient
function drawGradientOutline(poly,width,fillStyle,rgb1,rgb2){
ctx.beginPath();
var i = 0;
var w = canvas.width;
var h = canvas.height;
ctx.moveTo(poly[i++] * w,poly[i++] * h);
while(i < poly.length){
ctx.lineTo(poly[i++] * w,poly[i++] * h);
}
ctx.closePath();
var col1 = rgb2Array(rgb1);
var col2 = rgb2Array(rgb2);
i = width * 2;
var col = [];
while(i > 0){
ctx.lineWidth = i;
ctx.strokeStyle = array2rgb(lerpArr(col1,col2,1- i / (width * 2),col));
ctx.stroke();
i -= 1;
}
ctx.fillStyle = fillStyle;
ctx.fill();
}
ctx.clearRect(0,0,canvas.width,canvas.height)
ctx.lineJoin = "miter";
drawGradientOutline(poly,20,"black","rgb(255,0,0)","rgb(255,255,0)")
ctx.lineJoin = "round";
drawGradientOutline(poly1,20,"black","rgb(255,0,0)","rgb(255,255,0)")
基本上我需要为给定的多边形创建衰减纹理。例如这是我的图像
我需要创建的是这个,但是从白色到黑色的斜角渐变,将绿色部分视为渐变。
我得到了所有顶点的坐标和斜面的厚度。我正在使用 HTML5 2d canvas 进行渲染。基本上最明显的解决方案是计算每个像素到多边形的距离,如果它在厚度参数内,则计算颜色并为像素着色。但这是繁重的计算,而且会很慢,即使对于满足我需要的尽可能小的纹理也是如此。那么我可以用 canvas 来实现这个目标吗?
只需以不同的笔画宽度绘制多边形的轮廓,并根据宽度的每一步改变颜色。
该片段展示了一种实现方法。使用线连接 "miter" 和 "round"
绘制 2 个多边形 "use strict";
const canvas = document.createElement("canvas");
canvas.height = innerHeight;
canvas.width = innerWidth;
canvas.style.position = "absolute";
canvas.style.top = canvas.style.left = "0px";
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
// poly to draw
var poly = [0.1,0.2,0.4,0.5,0.2,0.8];
var poly1 = [0.6,0.1,0.9,0.5,0.8,0.9];
// convert rgb style colour to array
function rgb2Array(rgb){
var arr1 = rgb.split("(")[1].split(")")[0].split(",");
var arr = [];
while(arr1.length > 0){
arr.push(Number(arr1.shift()));
}
return arr;
}
// convert array to rgb colour
function array2rgb(arr){
return "rgb("+Math.floor(arr[0])+","+Math.floor(arr[1])+","+Math.floor(arr[2])+")"
}
// lerps array from to. Amount is from 0 @ from 1 @ to. res = is the resulting array
function lerpArr(from,to,amount,res){
var i = 0;
if(res === undefined){
res = [];
}
while(i < from.length){
res[i] = (to[i]-from[i]) * amount + from[i];
i++;
}
return res;
}
// draw gradient outline
// poly is the polygon verts
// width is the outline width
// fillStyle is the polygon fill style
// rgb1 is the outer colour
// rgb2 is the inner colour of the outline gradient
function drawGradientOutline(poly,width,fillStyle,rgb1,rgb2){
ctx.beginPath();
var i = 0;
var w = canvas.width;
var h = canvas.height;
ctx.moveTo(poly[i++] * w,poly[i++] * h);
while(i < poly.length){
ctx.lineTo(poly[i++] * w,poly[i++] * h);
}
ctx.closePath();
var col1 = rgb2Array(rgb1);
var col2 = rgb2Array(rgb2);
i = width * 2;
var col = [];
while(i > 0){
ctx.lineWidth = i;
ctx.strokeStyle = array2rgb(lerpArr(col1,col2,1- i / (width * 2),col));
ctx.stroke();
i -= 1;
}
ctx.fillStyle = fillStyle;
ctx.fill();
}
ctx.clearRect(0,0,canvas.width,canvas.height)
ctx.lineJoin = "miter";
drawGradientOutline(poly,20,"black","rgb(255,0,0)","rgb(255,255,0)")
ctx.lineJoin = "round";
drawGradientOutline(poly1,20,"black","rgb(255,0,0)","rgb(255,255,0)")