之前在用h5做物理课件的时候发现,对于非整数的线,h5在渲染上有问题。
flash在课件开发中的优势
游标卡尺,对于刻度的准确性,要求是很严格的,毕竟,游标卡尺就是靠上下两层刻度相差的1/10mm来实现精确测量的。
渲染上的问题,导致直接显示错误了。无法准确的测量。
专业的矢量渲染,会好很多,比如flash,比如svg。
我们想要在canvas中实现一个游标卡尺,缩放的时候,要求保持准确性,有没有什么办法呢?
之前的文章中已经提到过,用canvas自身的方法,似乎是行不通的。
我们可以尝试自己去写渲染算法。
参考:
Computer Graphics from Scratch
我们这个问题,属于图像缩小,找图像缩小的算法。
我尝试了3种方法,第一种:最近邻插值:直接取最近的像素值作为新的像素值。
第二种:双线性插值:利用周围两个像素点的加权平均值作为新的像素值。
第三种:原图像的像素点加权平局赋值给目标像素。
效果如下:
代码如下:
<html> <head> <script> var canvas,ctx,input,select; var data0 = []; var data1 = []; for(var i = 0; i < 1800; i++) { data0[i] = (i % 10 <= 2) ? 0 : 1; data1[i] = (i % 9 <= 2) ? 0 : 1; } window.onload = function(){ canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); input = document.getElementById("input"); select = document.getElementById("select"); setData(10, 100, data0); setData(10, 110, data1); onInput(); } function onChange(e){ //console.log("change"); } function onInput(e) { // console.log("input",input.value); ctx.clearRect(0, 200, 1900, 20); var w = input.value; var m = select.selectedIndex; var data2 = suoxiao(data0, w, m); var data3 = suoxiao(data1, w, m); setData(10, 200, data2); setData(10, 210, data3); } function suoxiao(data, w, m) { var n = data.length; var s = n / w; var a = []; for(var i = 0; i < w; i++){ a[i] = 0; } if(m == 1) { for(var i = 0; i < w; i++) { var j = i * s; var j0 = Math.floor(j); var j1 = Math.ceil(j); var v0 = data[j0]; var v1 = data[j1]; var f = j - j0; a[i] = (v1 * f) + v0 * (1-f); } } else if(m == 2){ for(var i = 0; i < n; i++) { var j = i / s; var v = data[i] / s; var j0 = Math.floor(j); var j1 = Math.ceil(j); var f = j - j0; if(j0 >= 0 && j0 < w) a[j0] += v * (1-f); if(j1 >= 0 && j1 < w) a[j1] += v * f; } } else { for(var i = 0; i < w; i++) { var j = Math.round(i * s); a[i] = data[j]; } } return a; } function setData(x, y, data0){ var w = data0.length; var imgData = ctx.getImageData(x, y, w, 10); for(var i = 0; i < w; i++) { for(var j = 0; j < 10; j++){ var n = (j * w + i) * 4; imgData.data[n] = data0[i] * 255; imgData.data[n + 1] = data0[i] * 255; imgData.data[n + 2] = data0[i] * 255; imgData.data[n + 3] = 255; } } ctx.putImageData(imgData, x, y); } </script> </head> <body> <select id="select"> <option value="1">方法一</option> <option value="2">方法二</option> <option value="3">方法三</option> </select> <input id="input" type="range" min="1" max="3800" value="1800" step="1" style="width: 1900px;" onchange="onChange()" oninput="onInput()"/> <canvas id="canvas" width="1900" height="1000" style="width: 1900px;height: 1000px;border: solid 1px red;"></canvas> </body> </html>
方法一效果和原生的差不多。
方法二好一点。方法三效果更好。
对于放大的场景,方法三有问题,可以用方法二,或者方法一,或者直接用原生的。
游标卡尺的刻度计算是一维问题,计算量也不是很大。在显示的时候我们取了高度10像素,实际使用的时候,高度1像素就行,拉伸成10像素。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。