HTML5 Canvas 当 window 很大时,alpha 透明度在 firefox 中对曲线不起作用
HTML5 Canvas alpha transparency doesn't work in firefox for curves when window is big
我在 HTML5 canvas 上绘制一条曲线,并使用 alpha 透明度创建发光效果,方法是在下面绘制一条 alpha 小于 1 的较粗版本的曲线,然后在顶部绘制更细的曲线(我正在使用多个递归级别来执行此操作)。
好的,问题来了。它的工作方式完全符合我在 Chrome 中的要求,提供了美丽的发光效果。但是在 Firefox 中,如果我的浏览器尺寸大于大约 300 像素的高度,alpha 将无法正确呈现(是的,这听起来很疯狂,但出于某种原因,它实际上就是这样做的)。如果我将浏览器的大小调整得非常小,那么 alpha 会突然起作用,我会得到令人惊叹的光芒。一旦我将 window 设置为合理的大小,alpha 就不再起作用,所以我得到的不是一条发光的线,而是一条非常粗的线。 :( 代码如下。
HTML:
<body>
<canvas id="viewport">
<script type="text/javascript" src="scripts/render.js"></script>
</body>
CSS:
* {
background-color:#000000;
padding:0px;
margin:0px;
width:100%;
height:100%;
overflow:hidden;
}
#viewport {
border:0px;
}
Javascript:
window.viewport = document.getElementById("viewport");
window.context = viewport.getContext("2d");
window.xFactor = 1;
window.yFactor = 1;
function initializeViewport() {
maximizeViewport();
setFactors();
}
function maximizeViewport() {
viewport.width = window.innerWidth;
viewport.height = window.innerHeight;
}
function setFactors() {
xFactor = window.innerWidth / 100;
yFactor = window.innerHeight / 100;
}
function absX(x) {
return Math.floor(x * xFactor);
}
function absY(y) {
return Math.floor(y * yFactor);
}
function drawQuadraticCurve(startX, startY, controlX, controlY, endX, endY, lineWidth, gradient, alpha, glowiness, glowLevel) {
glowLevel = (typeof glowLevel === 'undefined') ? 0 : glowLevel;
// Draw the glow first
if (glowLevel < glowiness) {
drawQuadraticCurve(startX, startY, controlX, controlY, endX, endY, lineWidth + Math.sqrt(glowLevel), gradient, alpha*0.65, glowiness, glowLevel + 1);
}
// Then draw the curve
context.beginPath();
context.moveTo(absX(startX), absY(startY));
context.quadraticCurveTo(absX(controlX), absY(controlY), absX(endX), absY(endY));
context.lineWidth = lineWidth;
context.strokeStyle = gradient;
context.globalAlpha = alpha;
context.shadowColor = "#FFFFFF";
context.shadowBlur = 0;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.stroke();
}
function createRadialGradient(colors, innerX, innerY, innerR, outerX, outerY, outerR) {
var gradient = context.createRadialGradient(absX(innerX),absY(innerY),Math.min(absX(innerR/2), absY(innerR/2)),absX(outerX),absY(outerY),Math.min(absX(outerR/2), absY(outerR/2)));
var gradientLength = colors.length;
for (i=0; i<gradientLength; i++) {
gradient.addColorStop(colors[i][0], colors[i][1]);
}
return gradient;
}
initializeViewport();
drawQuadraticCurve(80,65,20,70,70,10, 1,createRadialGradient([[0,"#FFFFFF"],[0.7,"#33CCFF"],[1,"#9944FF"]],50,50,1,50,50,90),1,8,0);
它在 Chrome 中工作的屏幕截图:http://i.imgur.com/brVT2i6.png
无法在 Firefox 中运行的屏幕截图:http://i.imgur.com/63Z4PJY.png
在我将 window 的大小调整得离谱之后它在 Firefox 中运行的屏幕截图:http://i.imgur.com/d9AihEu.png
第一个 可行的解决方案 获得赞成票和绿色复选标记!耶!
这确实是一条评论,但它不适合分配给评论的 space。 :-)
我咨询过 Html5 Canvas 的全知神谕——w3.org。
如果您指定一个零阴影模糊(正如您所做的那样),规范说应该没有应用阴影。
这意味着具有较大 canvas 大小的 FF 正确应用 w3 标准(不绘制任何阴影)并且 Chrome 和 FF(较小的版本)错误地应用了本不应应用的阴影。
http://www.w3.org/TR/2dcontext/
Shadows are only drawn if the opacity component of the alpha component
of the color of shadowColor is non-zero and either the shadowBlur is
non-zero, or the shadowOffsetX is non-zero, or the shadowOffsetY is
non-zero.
因此,要具有跨浏览器兼容性,您不能依赖 shadowBlur=0
时渲染中的怪癖。您必须在 "rules".
中以另一种方式创建您的光晕
这是一条发光的二次曲线,由细小的、独立的线段组成——每条线段都有不同的颜色。等于段颜色的 shadowColor 会导致发光。渲染跨浏览器(包括 FF)兼容。
(可以控制线宽和发光强度)
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// variables to define colors -- use hsl instead of rgb
var hue=10;
var hueShift=4;
// define the quadratic curve
var startPt={x:350,y:100};
var controlPt={x:0,y:250};
var endPt={x:350,y:400};
// variables defining the starting & ending point of
// the current line segment.
var newXY=startPt;
var oldXY=startPt;
// the current interval along the quadratic curve
// (used to calc an x,y along the curve)
// (t is kind-of like a percentage along the curve--kind of but not)
var t=0;
// the unshadowed linewidth
ctx.lineWidth=1;
// the shadow to apply around the line
ctx.shadowBlur=7;
// round the endcaps to visually blend the line segments
ctx.lineCap='round';
// start with a black-filled canvas
ctx.fillStyle='black';
ctx.fillRect(0,0,cw,ch);
// start the animation
requestAnimationFrame(animate);
function animate(time){
// calculate a new x,y along the curve
var T=t/100;
var newXY=getQuadraticBezierXYatT(startPt,controlPt,endPt,T);
// change the color for this segment
hue=(hue+hueShift)%360;
// draw this line segment with a shadow-glow
glowLine(oldXY,newXY,hue);
// set old=new in preparation for the next loop
oldXY=newXY;
// request another animation loop intil reaching 100
if(++t<100){
requestAnimationFrame(animate);
}
}
function glowLine(oldXY,newXY,hue){
// calculate the hsl color given the new hue
var hsl="hsl(" + (hue % 360) + ",99%,50%)";
// draw a glowing line segment
// (==a line segment with a shadow of the same color as the line segment)
ctx.beginPath();
ctx.moveTo(oldXY.x,oldXY.y);
ctx.lineTo(newXY.x,newXY.y);
ctx.fillStyle= hsl
ctx.strokeStyle=hsl;
ctx.shadowColor=hsl;
// overdraw the line segment so it really stands out
for(var i=0;i<6;i++){
ctx.stroke();
}
}
// calculate an [x,y] along a quadratic curve given an interval T
function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) {
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;
return( {x:x,y:y} );
}
body{ background-color:ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=500 height=500></canvas>
我在 HTML5 canvas 上绘制一条曲线,并使用 alpha 透明度创建发光效果,方法是在下面绘制一条 alpha 小于 1 的较粗版本的曲线,然后在顶部绘制更细的曲线(我正在使用多个递归级别来执行此操作)。
好的,问题来了。它的工作方式完全符合我在 Chrome 中的要求,提供了美丽的发光效果。但是在 Firefox 中,如果我的浏览器尺寸大于大约 300 像素的高度,alpha 将无法正确呈现(是的,这听起来很疯狂,但出于某种原因,它实际上就是这样做的)。如果我将浏览器的大小调整得非常小,那么 alpha 会突然起作用,我会得到令人惊叹的光芒。一旦我将 window 设置为合理的大小,alpha 就不再起作用,所以我得到的不是一条发光的线,而是一条非常粗的线。 :( 代码如下。
HTML:
<body>
<canvas id="viewport">
<script type="text/javascript" src="scripts/render.js"></script>
</body>
CSS:
* {
background-color:#000000;
padding:0px;
margin:0px;
width:100%;
height:100%;
overflow:hidden;
}
#viewport {
border:0px;
}
Javascript:
window.viewport = document.getElementById("viewport");
window.context = viewport.getContext("2d");
window.xFactor = 1;
window.yFactor = 1;
function initializeViewport() {
maximizeViewport();
setFactors();
}
function maximizeViewport() {
viewport.width = window.innerWidth;
viewport.height = window.innerHeight;
}
function setFactors() {
xFactor = window.innerWidth / 100;
yFactor = window.innerHeight / 100;
}
function absX(x) {
return Math.floor(x * xFactor);
}
function absY(y) {
return Math.floor(y * yFactor);
}
function drawQuadraticCurve(startX, startY, controlX, controlY, endX, endY, lineWidth, gradient, alpha, glowiness, glowLevel) {
glowLevel = (typeof glowLevel === 'undefined') ? 0 : glowLevel;
// Draw the glow first
if (glowLevel < glowiness) {
drawQuadraticCurve(startX, startY, controlX, controlY, endX, endY, lineWidth + Math.sqrt(glowLevel), gradient, alpha*0.65, glowiness, glowLevel + 1);
}
// Then draw the curve
context.beginPath();
context.moveTo(absX(startX), absY(startY));
context.quadraticCurveTo(absX(controlX), absY(controlY), absX(endX), absY(endY));
context.lineWidth = lineWidth;
context.strokeStyle = gradient;
context.globalAlpha = alpha;
context.shadowColor = "#FFFFFF";
context.shadowBlur = 0;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.stroke();
}
function createRadialGradient(colors, innerX, innerY, innerR, outerX, outerY, outerR) {
var gradient = context.createRadialGradient(absX(innerX),absY(innerY),Math.min(absX(innerR/2), absY(innerR/2)),absX(outerX),absY(outerY),Math.min(absX(outerR/2), absY(outerR/2)));
var gradientLength = colors.length;
for (i=0; i<gradientLength; i++) {
gradient.addColorStop(colors[i][0], colors[i][1]);
}
return gradient;
}
initializeViewport();
drawQuadraticCurve(80,65,20,70,70,10, 1,createRadialGradient([[0,"#FFFFFF"],[0.7,"#33CCFF"],[1,"#9944FF"]],50,50,1,50,50,90),1,8,0);
它在 Chrome 中工作的屏幕截图:http://i.imgur.com/brVT2i6.png
无法在 Firefox 中运行的屏幕截图:http://i.imgur.com/63Z4PJY.png
在我将 window 的大小调整得离谱之后它在 Firefox 中运行的屏幕截图:http://i.imgur.com/d9AihEu.png
第一个 可行的解决方案 获得赞成票和绿色复选标记!耶!
这确实是一条评论,但它不适合分配给评论的 space。 :-)
我咨询过 Html5 Canvas 的全知神谕——w3.org。
如果您指定一个零阴影模糊(正如您所做的那样),规范说应该没有应用阴影。
这意味着具有较大 canvas 大小的 FF 正确应用 w3 标准(不绘制任何阴影)并且 Chrome 和 FF(较小的版本)错误地应用了本不应应用的阴影。
http://www.w3.org/TR/2dcontext/
Shadows are only drawn if the opacity component of the alpha component of the color of shadowColor is non-zero and either the shadowBlur is non-zero, or the shadowOffsetX is non-zero, or the shadowOffsetY is non-zero.
因此,要具有跨浏览器兼容性,您不能依赖 shadowBlur=0
时渲染中的怪癖。您必须在 "rules".
这是一条发光的二次曲线,由细小的、独立的线段组成——每条线段都有不同的颜色。等于段颜色的 shadowColor 会导致发光。渲染跨浏览器(包括 FF)兼容。
(可以控制线宽和发光强度)
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// variables to define colors -- use hsl instead of rgb
var hue=10;
var hueShift=4;
// define the quadratic curve
var startPt={x:350,y:100};
var controlPt={x:0,y:250};
var endPt={x:350,y:400};
// variables defining the starting & ending point of
// the current line segment.
var newXY=startPt;
var oldXY=startPt;
// the current interval along the quadratic curve
// (used to calc an x,y along the curve)
// (t is kind-of like a percentage along the curve--kind of but not)
var t=0;
// the unshadowed linewidth
ctx.lineWidth=1;
// the shadow to apply around the line
ctx.shadowBlur=7;
// round the endcaps to visually blend the line segments
ctx.lineCap='round';
// start with a black-filled canvas
ctx.fillStyle='black';
ctx.fillRect(0,0,cw,ch);
// start the animation
requestAnimationFrame(animate);
function animate(time){
// calculate a new x,y along the curve
var T=t/100;
var newXY=getQuadraticBezierXYatT(startPt,controlPt,endPt,T);
// change the color for this segment
hue=(hue+hueShift)%360;
// draw this line segment with a shadow-glow
glowLine(oldXY,newXY,hue);
// set old=new in preparation for the next loop
oldXY=newXY;
// request another animation loop intil reaching 100
if(++t<100){
requestAnimationFrame(animate);
}
}
function glowLine(oldXY,newXY,hue){
// calculate the hsl color given the new hue
var hsl="hsl(" + (hue % 360) + ",99%,50%)";
// draw a glowing line segment
// (==a line segment with a shadow of the same color as the line segment)
ctx.beginPath();
ctx.moveTo(oldXY.x,oldXY.y);
ctx.lineTo(newXY.x,newXY.y);
ctx.fillStyle= hsl
ctx.strokeStyle=hsl;
ctx.shadowColor=hsl;
// overdraw the line segment so it really stands out
for(var i=0;i<6;i++){
ctx.stroke();
}
}
// calculate an [x,y] along a quadratic curve given an interval T
function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) {
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;
return( {x:x,y:y} );
}
body{ background-color:ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=500 height=500></canvas>