在动画过程中可见的画布背景

Background of Canvas visible during animation

本文关键字:布背景 背景 动画 过程中      更新时间:2023-09-26

感谢另一位 SO 友好地帮助我完成这项任务,我有一个画布元素成功地以我想要的方式对圆进行动画处理。但是,当动画发生时,画布的背景是可见的,因此会覆盖画布后面的任何内容。我知道画布默认有透明背景,但我相信这实际上是无关的......

请参阅以下示例,了解已实现的内容以及整个初始动画中发生的错误。

https://jsfiddle.net/sm8ozqLg/1/

我相信有问题的代码如下:

function convertToRadians(degree) {
    return degree*(Math.PI);
}
var canvas = document.getElementById('progress');
var context = canvas.getContext('2d');
function showProgress(percent){
    console.log(percent);
    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;
    var sections = 6;
    var radius = 106;
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
    var grd = context.createLinearGradient(canvas.width, 0, 0, canvas.height);
    grd.addColorStop(0, '#d586f4');   
    grd.addColorStop(1, '#5c00d2');
    context.fillStyle = grd;
    context.fill();
    context.beginPath();
    if (percent){
        var amt = ((2 / 100) * percent) + 1.5;
        if (amt > 2) amt = amt - 2;
        context.arc(centerX, centerY, radius, amt * Math.PI, 1.5 * Math.PI, false); //25%
    } else context.arc(centerX, centerY, radius, 0 * Math.PI, 2 * Math.PI, false); //0%
    context.lineWidth = (radius - .3) * 2;
    context.strokeStyle = '#ffffff';
    context.stroke();
}
var timer = setInterval(function(){ runTimer() }, 20);
var t = 0;
function runTimer(){
    if (t == 101) stopTimer();
    context.clearRect(0, 0, canvas.width, canvas.height);
    showProgress(t);
    t++;
}
function stopTimer() {
    clearInterval(myVar);
}

谁能弄清楚为什么白色覆盖其他元素?

试试这个:

function toRad(degrees) { return degrees * (Math.PI / 180); }
function map(value, minIn, maxIn, minOut, maxOut) {
  return (value - minIn) * (maxOut - minOut) / (maxIn - minIn) + minOut;
}
var canvas = document.getElementById('progress');
var context = canvas.getContext('2d');
function showProgress(percent) {
  var centerX = canvas.width / 2;
  var centerY = canvas.height / 2;
  var sections = 6;
  var radius = 94;
  context.beginPath();
  context.arc(centerX, centerY, radius, toRad(-90), toRad(map(percent, 0, 100, -90, 270)), false);
  var grd = context.createLinearGradient(canvas.width, 0, 0, canvas.height);
  grd.addColorStop(0, '#d586f4');
  grd.addColorStop(1, '#5c00d2');
  context.lineWidth = 22;
  context.strokeStyle = grd;
  context.stroke();
}
function runTimer() {
  if (t == 101) stopTimer();
  context.clearRect(0, 0, canvas.width, canvas.height);
  showProgress(t);
  t++;
}
function stopTimer() { clearInterval(timer); }
var timer = setInterval(function () { runTimer(); }, 20);
var t = 0;
html, body {
    background: #f5f5f5;
}
#progress_container {
    position: absolute;
    border-radius: 50%;
    width: 240px;
    height: 240px;
    top: 50%;
    left: 50%;
    margin-top: -120px;
    margin-left: -120px;
    background: #D0D2D5;
    background: -moz-linear-gradient(top, #d0d2d5 0%, #ffffff 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d0d2d5), color-stop(100%, #ffffff));
    background: -webkit-linear-gradient(top, #d0d2d5 0%, #ffffff 100%);
    background: -o-linear-gradient(top, #d0d2d5 0%, #ffffff 100%);
    background: -ms-linear-gradient(top, #d0d2d5 0%, #ffffff 100%);
    background: linear-gradient(to bottom, #d0d2d5 0%, #ffffff 100%);
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0d2d5', endColorstr='#ffffff', GradientType=0);
    -webkit-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15);
    -moz-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15);
    box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15);
    z-index: 5;
}
#progress_dial {
    position: absolute;
    border-radius: 50%;
    width: 212px;
    height: 212px;
    margin: 14px;
    -webkit-box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    z-index: 6;
}
#progress_shadow {
    position: absolute;
    border-radius: 50%;
    width: 212px;
    height: 212px;
    margin: 14px;
    -webkit-box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    box-shadow: inset 0px 3px 5px 0px rgba(5, 71, 110, 0.51), inset 0px 0px 19px 0px rgba(0, 0, 0, 0.2);
    z-index: 8;
}
#progress {
    position: absolute;
    margin: 9px;
    z-index: 7;
}
#progress_content {
    position: absolute;
    border-radius: 50%;
    width: 170px;
    height: 170px;
    margin: 21px;
    background: #fafafb;
    background-image: url("//images.domain.com/_index/bg-noise.png");
    background-image: url("//images.domain.com/_index/bg-noise.png"), -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafb), color-stop(100%, #e1e2e5));
    background-image: url("//images.domain.com/_index/bg-noise.png"), -webkit-linear-gradient(top, #fafafb 0%, #e1e2e5 100%);
    background-image: url("//images.domain.com/_index/bg-noise.png"), -moz-linear-gradient(top, #fafafb 0%, #e1e2e5 100%);
    background-image: url("//images.domain.com/_index/bg-noise.png"), -o-linear-gradient(top, #fafafb 0%, #e1e2e5 100%);
    background-image: url("//images.domain.com/_index/bg-noise.png"), -ms-linear-gradient(top, #fafafb 0%, #e1e2e5 100%);
    background-image: url("//images.domain.com/_index/bg-noise.png"), linear-gradient(to bottom, #fafafb 0%, #e1e2e5 100%);
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e1e2e5', GradientType=0);
    -webkit-box-shadow: 0px 0px 19px 0px rgba(0, 0, 0, 0.2), 0px 0px 3px 1px rgba(0, 0, 0, 0.3), inset 0px -1px 2px 1px rgba(32, 46, 61, 0.9);
    -moz-box-shadow: 0px 0px 19px 0px rgba(0, 0, 0, 0.2), 0px 0px 3px 1px rgba(0, 0, 0, 0.3), inset 0px -1px 2px 1px rgba(32, 46, 61, 0.9);
    box-shadow: 0px 0px 19px 0px rgba(0, 0, 0, 0.2), 0px 0px 3px 1px rgba(0, 0, 0, 0.3), inset 0px -1px 2px 1px rgba(32, 46, 61, 0.9);
    z-index: 9;
}
h1#progress_percentage {
    position: relative;
    margin: 35px 0 0 0;
    z-index:10;
    text-shadow: 0px 1px 1px #fff;
    display: block;
    color: #777;
    font-family:'Open Sans', sans-serif;
    font-weight: 800;
    font-size: 60px;
    padding: 0;
    text-align: center;
    width: 170px;
}
h1#progress_percentage:before {
    content: attr(title);
    position: absolute;
    display: block;
    color: rgba(255, 255, 255, .4);
    text-align: center;
    width: 170px;
    text-shadow: none;
    top: 1px;
    left: 1px;
}
h2#progress_value {
    position: absolute;
    display: block;
    margin: -8px 0 0 0;
    color: #777;
    font-family:'Open Sans', sans-serif;
    font-weight: 800;
    font-size: 18px;
    padding: 0;
    text-align: center;
    width: 170px;
    z-index:10;
    text-shadow: 0px 1px 1px #fff;
}
h2#progress_value:before {
    content: attr(title);
    position: absolute;
    display: block;
    color: rgba(255, 255, 255, .4);
    text-align: center;
    width: 170px;
    top: 1px;
    left: 1px;
    text-shadow: none;
}
<div id="progress_container">
    <svg id="progress_dial" width="212px" height="212px">
        <path d="M 0 106 C 0 47.4571 47.4571 0 106 0 C 164.5429 0 212 47.4571 212 106 C 212 164.5429 164.5429 212 106 212 C 47.4571 212 0 164.5429 0 106 Z" fill="#e0e1e5" />
        <path opacity="0.3882" d="M 106.5 0.5 L 106.5 212.5 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 133.9519 3.9825 L 79.0822 208.7587 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 159.517 14.5719 L 53.517 198.1693 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 181.4704 31.4173 L 31.5637 181.3239 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 198.3157 53.3706 L 14.7183 159.3706 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 208.9052 78.9358 L 4.1289 133.8054 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 212.517 106.3706 L 0.517 106.3706 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 209.0346 133.8224 L 4.2583 78.9528 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 198.4451 159.3876 L 14.8478 53.3876 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 181.5998 181.341 L 31.6931 31.4343 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 159.6464 198.1863 L 53.6465 14.5889 " stroke="#ffffff" stroke-width="1" />
        <path opacity="0.3882" d="M 134.0813 208.7758 L 79.2116 3.9995 " stroke="#ffffff" stroke-width="1" />
    </svg>
    <div id="progress_shadow">
        <div id="progress_content">
             <h1 id="progress_percentage" title="0%">0%</h1>
        </div>
    </div>
    <canvas id="progress" width="224" height="224"></canvas>
</div>

详:

  • 这里的想法是,您不需要创建两个单独的形状使用 arc 方法,但相反,您可以实现所需的通过及时仅对 arc 方法使用一次调用来生成结果。
  • 其次,我们需要一种方法来将度转换为弧度,以用于我们的arc这里通过toRad()方法完成的方法。
  • 我们还需要map一个介于一个范围之间的值,以映射/转换/传输到另一个范围。在这里,percent是价值落在0100之间。它被映射到一系列-90270。我们可以将它们映射到 0360但我们需要从top开始的圆圈和 center点位置,即90度减法。
  • 最后,需要对#progress元素的 CSS margin规则以及 HTML 中的canvas对象应用一些小的调整,需要更大的widthheight。另外,JavaScript 中的 radius 变量也需要调整,lineWidth需要是一个精确的数字。

希望这有帮助。

请检查

以下小提琴。我已经在那里更新了它。

JS小提琴

function convertToRadians(degree) {
        return degree*(Math.PI);
    }
    var canvas = document.getElementById('progress');
    var context = canvas.getContext('2d');
    function showProgress(percent){
        console.log(percent);
        var centerX = canvas.width / 2;
        var centerY = canvas.height / 2;
        var sections = 6;
        var radius = 106;
        context.beginPath();
        context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
        var grd = context.createLinearGradient(canvas.width, 0, 0, canvas.height);
        grd.addColorStop(0, '#d586f4');   
        grd.addColorStop(1, '#5c00d2');
        context.fillStyle = grd;
        context.fill();
        context.beginPath();
        if (percent){
            var amt = ((2 / 100) * percent) + 1.5;
            if (amt > 2) amt = amt - 2;
            context.arc(centerX, centerY, radius, amt * Math.PI, 1.5 * Math.PI, false); //25%
        } else context.arc(centerX, centerY, radius, 0 * Math.PI, 2 * Math.PI, false); //0%
        context.lineWidth = (radius - .3) * 2;
        context.strokeStyle = '#ffffff';
        context.stroke();
    }
    var timer = setInterval(function(){ runTimer() }, 20);
    var t = 0;
    function runTimer(){
        if (t == 101) stopTimer();
        context.clearRect(0, 0, canvas.width, canvas.height);
        showProgress(t);
        t++;
    }
    function stopTimer() {
        clearInterval(myVar);
    }