当窗口很大时,HTML5 Canvas alpha透明度在firefox中不适用于曲线

时间:2015-02-13 03:35:15

标签: javascript html5 firefox canvas transparency

我在HTML5画布上绘制一条曲线并使用Alpha透明度创建一个发光效果,方法是在下面绘制一个较小版本的曲线,其alpha值小于1,然后绘制一个更薄的曲线版本顶部(我正在使用几个递归级别执行此操作)。

好的,这是问题所在。它的工作方式与我想要的方式完全一致,给人一种美丽的发光效果。但是在Firefox中,如果我的浏览器尺寸大于300px的高度,那么alpha就无法正常渲染(是的,听起来很疯狂,但实际上它正是出于某种原因)。如果我将浏览器的大小调整得非常小,那么阿尔法就会突然发挥作用,我会得到令人敬畏的光芒。一旦我将窗口设置为合理的尺寸,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

在我将窗口调整为非常小的窗口之后,在Firefox中工作的屏幕截图:http://i.imgur.com/d9AihEu.png

首个工作解决方案获得一个upvote和一个绿色复选标记!耶!

2 个答案:

答案 0 :(得分:1)

这实际上是一个评论,但它不适合分配给评论的空间。 : - )

我已经咨询了Html5 Canvas的全知 - Oracle - w3.org。

如果您指定零shadowBlur(正如您所做),则规格应该不应用阴影。

这意味着具有较大画布尺寸的FF正确应用w3标准(不绘制任何阴影)以及Chrome和&amp ;; FF(较小版本)不应该应用阴影。

http://www.w3.org/TR/2dcontext/

  

仅在alpha组件的不透明度组件中绘制阴影   shadowColor的颜色是非零,shadowBlur是   非零,或者shadowOffsetX为非零,或者shadowOffsetY为   非零的。

因此,为了实现跨浏览器兼容性,在shadowBlur=0时,您不能依赖渲染中的怪癖。你必须在“规则”中以另一种方式创造你的光芒。

答案 1 :(得分:1)

enter image description here

这是一条由小的单独线段组成的发光二次曲线 - 每个线段都是不同的颜色。 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>