Kev*_*ose 0 html javascript html5-canvas web
浏览器如何渲染html画布的内容?像 context.lineTo(x, y) 这样的东西。必须有某个组件将所有函数调用转换为像素数据。我真正想知道的是是否有某种方法可以获取这些像素数据而不需要实际将其渲染到某个地方。
我想知道我们是否可以运行某种独立的 JavaScript 引擎(v8)并将 JavaScript 代码传递给它并获取像素数据作为输出。
浏览器(或显卡)只是应用数学算法来设置像素。
结果存储在 Html Canvas 维护的后备数组中,以保存每个像素的状态。
每个画布像素由画布像素数组中的一组 4 个元素表示。4 个像素集是 R、G、B、A 值。因此,单个红色像素将由像素数组中的这组 4 个元素表示:
pixelArray=[...255,0,0,255...] // where 255==red, 0==green, 0==blue, alpha==255
Run Code Online (Sandbox Code Playgroud)
您无法访问浏览器的内部像素设置算法,但可以运行相同的算法来设置适当的像素。
以下是如何做到这一点的概述:
假设您有一个代表假想网格上所有像素的数组:
var width=500;
var height=500;
var pixels=new Array(width*height);
Run Code Online (Sandbox Code Playgroud)
您可以像这样获取与任何像素对应的数组元素:
var x=200;
var y=30;
var arrayElement=y*width+x;
Run Code Online (Sandbox Code Playgroud)
您可以像这样设置数组像素元素:
function setPixel(x,y,colorObject){
pixels[y*width+x]=colorObject;
}
setPixel(100,50,{r:255,g:0,b:0,a:255});
Run Code Online (Sandbox Code Playgroud)
您可以获得任何 [x,y] 的像素设置,如下所示:
function getPixel(x,y){
return(pixels[y*width+x]);
}
var theColor=getPixel(100,50);
Run Code Online (Sandbox Code Playgroud)
然后你可以设置连接点 [x0,y0] 到 [x1,y1] 的线段上的像素,如下所示:
// Refer to: http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
function bline(x0, y0, x1, y1) {
var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
var dy = Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
var err = (dx>dy ? dx : -dy)/2;
while (true) {
setPixel(x0,y0);
if (x0 === x1 && y0 === y1) break;
var e2 = err;
if (e2 > -dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
Run Code Online (Sandbox Code Playgroud)
其他 Html Canvas Path 元素具有类似的算法,将计算需要沿路径设置的每个 [x,y] 像素。
Html 画布曲线路径
每个弯曲路径元素均由数学方程定义。您可以使用这些方程按一定时间间隔对值进行过采样,从而获得曲线上的每个 [x,y]。
例如,沿二次曲线以间隔 (T) 获取 [x,y] 点的公式如下。T 是 0.00 到 1.00 之间的值,其中 T==0.00 位于曲线的起点,T==1.00 位于曲线的终点。
// Get [x,y] at interval T along a Quadratic Curve
var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x;
var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y;
Run Code Online (Sandbox Code Playgroud)
您必须沿曲线对间隔 (T) 进行过采样,否则可能会丢失该曲线上的 [x,y] 点。这是因为与直线不同,曲线公式不会获取均匀间隔的点。下面是一个在 0.00 和 1.00 之间使用 1000 T 航路点进行过采样的示例。
// Oversample T along a quadratic curve to be sure to catch all [x,y]
// Some pixels will harmlessly be set more than once,
// but it's likely that all desired pixels will be set
for(var i=0;i<1000;i++){
var T=i/1000;
var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x;
var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y;
setPixel(x,y,color);
}
Run Code Online (Sandbox Code Playgroud)
沿三次贝塞尔曲线获取 [x,y] 点的公式如下。
// De Casteljau's algorithm which calculates points along a cubic Bezier curve
function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}
// cubic helper formula at T distance
function CubicN(T, a,b,c,d) {
var t2 = T * T;
var t3 = t2 * T;
return a + (-a * 3 + T * (3 * a - a * T)) * T
+ (3 * b + T * (-6 * b + b * 3 * T)) * T
+ (c * 3 - c * 3 * T) * t2
+ d * t3;
}
Run Code Online (Sandbox Code Playgroud)
沿指定弧度角获取 [x,y] 点的公式如下。
// Trigonometry to calculate [x,y] at a specified angle
function get ArcXYatRadianAngle(centerX,centerY,radius,radianAngle){
var x=centerX+radius*Math.cos(radianAngle);
var y=centerY+radius*Math.sin(radianAngle);
}
Run Code Online (Sandbox Code Playgroud)
Html 画布运算符
设置globalAlpha就像将alpha任何像素的元素设置为 0 到 255 之间(完全透明和完全不透明之间)的所需值一样简单。
即使是globalCompsiteOperation也相对简单。
提示:这种将现有像素与替换像素进行比较的方法也可用于将混合滤镜应用于您的像素!;-)
剪裁更加困难,因为您必须确保仅在指定的剪裁区域内应用新的像素值。您可以使用微积分来确定允许的绘图区域,但更简单的是:
哇!好吧,这应该可以让您开始...祝您的项目好运!
| 归档时间: |
|
| 查看次数: |
490 次 |
| 最近记录: |