Javascript 在画布上抚摸文本

Javascript 在画布上抚摸文本,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,我遇到了一个有趣的效果,在画布中混合了setLineDash和strokeText ctx=document.querySelector(“画布”).getContext(“2d”) ctx.font=“110px Arial”; i=速度=3 函数循环(){ ctx.clearRect(0,0,600,160) ctx.beginPath() ctx.setLineDash([i,600]); ctx.strokeText(“世界ふ", 10, 100); i+=速度 如果(i>600 |

我遇到了一个有趣的效果,在画布中混合了
setLineDash
strokeText

ctx=document.querySelector(“画布”).getContext(“2d”)
ctx.font=“110px Arial”;
i=速度=3
函数循环(){
ctx.clearRect(0,0,600,160)
ctx.beginPath()
ctx.setLineDash([i,600]);
ctx.strokeText(“世界ふ", 10, 100);
i+=速度
如果(i>600 | | i<2)
速度*=-1
}
设置间隔(循环,50)

您可以在屏幕外绘制每个字符,并“计算”像素的出现次数(非零值):

函数getAmount(字符,{宽度、高度、字体、颜色}){ //创建临时屏幕外画布 const canvas=document.createElement('canvas') canvas.width=宽度 canvas.height=高度 //画人物 const ctx=canvas.getContext(“2d”) ctx.font=font ctx.strokeText(字符,0,90) //获取像素数据 常量imageData=ctx.getImageData(0,0,宽度,高度) 设和=0 imageData.data.forEach(点=>{ 如果(点>0)和++ }) 回报金额 } 常数宽度=90 常数高度=90 const font=“90px Arial” getAmount('W',{font,width,height})//940 getAmount('O',{font,width,height})//660 getAmount('R',{font,width,height})//673 getAmount('L',{font,width,height})//296 getAmount('D',{font,width,height})//613 您可以大致使用这些值作为速度权重,并单独绘制每个字符,但请记住,您必须管理放置等。此外,这仅检测任何非零值。如果您使用笔划渐变,则必须检测渐变范围内的图像数据

编辑: 既然找不到真相的来源,我们可以使用另一个技巧:

查找创建与完整虚线字符像素量相同的屏幕外图像的
i

/**
*按给定参数将带笔划的文本绘制到上下文
**/
函数绘图(字符、ctx、最小值、最大值){
ctx.clearRect(0,0,600,160)
ctx.beginPath()
if(最小值和最大值){
ctx.setLineDash([minValue,maxValue])
}
ctx.strokeText(char,10100);
}
/**
*返回给定字符的像素量
*/
const offscreenCanvas=document.createElement('canvas')
函数getAmount(char,{value,max,width,height,font}){
//在屏幕外绘制,然后检测边界像素
offscreenCanvas.width=宽度
offscreenCanvas.height=高度
//画人物
const ctx=offscreenCanvas.getContext(“2d”)
ctx.font=font
绘制(字符、ctx、值、最大值)
//获取像素数据
常量imageData=ctx.getImageData(0,0,宽度,高度)
设和=0
imageData.data.forEach(点=>{
如果(点>0)和++
})
回报金额
}
/**
*返回完成字符所需的迭代次数
**/
函数getIterations(char,{font,width,height}){
//完全提取单词时获取金额
const fullAmount=getAmount(字符,{value:undefined,max:undefined,width,height,font})
设迭代次数=1
让数量=0
做{
amount=getAmount(字符,{value:iterations,max:1000,宽度,高度,字体})
迭代++
}而((金额-全额<-3)和迭代次数<2000);
返回迭代
}
从这里我们可以确定
setLineDash
参数的
i
值:

const font=“110px Arial”;
常数宽度=110
常数高度=110
常量检查=字符=>{
const amount=getIterations(字符,{font,width,height})
console.log(字符、数量)
}
检查('W')//620
检查('O')//243
检查('R')//331
勾选('L')//248
检查('D')//248
支票('ふ') // 185
使用这些值,您可以创建相对<代码>速度参数,该参数允许您同时完成笔划


请注意,这种方法是超级贪婪的,不是真正的性能优化,而是概念验证。

这里是概念验证的优化版本:

功能字母(文本、字体){
const oc=document.createElement('canvas');
oc.宽度=oc.高度=200;
常量octx=oc.getContext(“2d”);
octx.globalCompositeOperation='copy';
octx.imageSmoothingEnabled=假;
octx.font=font;
功能像素(字符){
octx.strokeText(字符,20,oc.height-20);
const id=octx.getImageData(0,0,oc.width,oc.height)
返回id.data.reduce((a,c)=>c?a+1:a,0)
}
函数长度(字符){
octx.setLineDash([]);
常量满=像素(字符)
如果(full==0)返回0
设max=full
设min=0
做{
设iter=Math.round((最小+最大)/2)
octx.setLineDash([iter,800]);
如果(像素(字符)>满-10)
最大值=国际热核实验堆
其他的
min=国际热核实验堆
}而(最小值+1<最大值)
返回最大值
}
const strArray=text.split(“”);
返回strArray.map(s=>length(s));
}
ctx=document.getElementById(“c”).getContext(“2d”)
ctx.font=“110px Arial”;
i=delta=3
const world=“世界ふ"
const wlen=lettlen(world,ctx.font)
const minlen=Math.min(…wlen)
函数循环(){
ctx.clearRect(0,0,900,600)
常量字母=世界分割(“”);
设ix=10
对于(j=0;jminlen+10 | | i<2)
delta*=-1
}
设置间隔(循环,50)

可以假定边框有纯色(没有渐变色)?@Jankapunkt不完全确定你的意思……但我们肯定可以做出一些假设。最好的解决方案可能是强制使用web字体,这样所有客户都能得到相同的结果,并在专用软件中进行一次测量。@Kaido yes有意义,如果这是无法检索的,必须通过卸载计算得出的专用软件的计算将减少b