使用css和javascript调整svg动画时出错

Error while tweaking svg animation using css and javascript

本文关键字:动画 出错 svg 调整 css javascript 使用      更新时间:2023-09-26

我在codepen上发现了一个有趣的代码,我想复制并写同样的代码。我试过了,但没用。这是我得到它的链接http://codepen.io/thebabydino/pen/LpqEmJ

它在控制台上给我错误作为

 TypeError: rotor is null engine.js:176:1

代码如下:

HTML

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>For You</title>
<link href="style.css" rel="stylesheet">
<script type="application/javascript" src="engine.js"></script>
</head>
<body>
<p><a href='http://codepen.io/thebabydino/pen/RWvaZW' target='_blank'>see also the pure CSS (WebKit-only) version</a></p>
<svg viewbox='-2000 -2000 4000 4000'>
<g id='rotor'>
<polygon id='morpher'></polygon>
</g>
</svg>
<h1>click it, you know you want to!</h1>
</body>
</html>

CSS

html { text-align: center; }
body { background: #000; color: #fff; }
svg { width: 65vmin; hight: 65vmin; }
polygon { cursor: pointer; }
h1, p { font: 2em trebuchet ms, verdana, sans-serif; }
p { font-size: 1em; }
a { color: greenyellow; }

JS

// JavaScript Document
Object.getOwnPropertyNames(Math).map(function(p) {
    window[p] = Math[p];
});
var PRECISION = 4, 
    RC_PENTA = 500, 
    A_HEART = PI/4, 
    DURATION = 40, 
    END_SHADES = [[255, 215, 0], [220, 20, 60]], 
    tl = [], shades = [], 
    t = 0, t_incr = 1, rid = null,
    rotor = document.getElementById('rotor'), 
    morpher = document.getElementById('morpher');
var getData = function(prec, rc_penta, a_heart) {
var n_penta = 5, data = { 'prec': prec }, 
        ca_penta = 2*PI/n_penta, 
        ri_penta = rc_penta*cos(.5*ca_penta), 
        hl_penta = rc_penta*sin(.5*ca_penta), 
        ai_penta = (n_penta - 2)*PI/n_penta, 
        ao_penta = PI - ai_penta, 
        ho_star = hl_penta*tan(ao_penta), 
        d = rc_penta + ri_penta + ho_star, 
        diam_heart = d*sin(a_heart);
data.nvx_star = 2*n_penta;
data.ba_star = .5*ca_penta;
data.r_star = [ri_penta + ho_star, rc_penta];
data.nr_heart = n_penta*prec - 1;
data.r_heart = .5*diam_heart;
data.yu_heart = -diam_heart*sin(a_heart);
data.yl_heart = data.yu_heart + d;
data.xo_heart = data.r_heart*cos(a_heart);
data.yo_heart = .5*data.yu_heart;
data.ba_heart = PI/data.nr_heart;
data.aoff_heart = PI - a_heart;
return data;
};
var getEndpoints = function(data) {
var star = [], s1 = [], 
        heart = [{'x': 0, 'y': data.yl_heart}], 
        h1 = [], h2 = [], a, x, y, 
        xp, yp, x0, y0, k;
/* STAR */
for(var i = 0; i < data.nvx_star; i++) {
    a = i*data.ba_star + .5*PI;
    x = data.r_star[i%2]*cos(a);
    y = data.r_star[i%2]*sin(a);

    if(xp && yp) {
        for(var j = 0; j < data.prec; j++) {
            k = j/data.prec;
            star.push({
                'x': k*x + (1 - k)*xp, 
                'y': k*y + (1 - k)*yp
            });
            if(i === data.nvx_star - 1) {
                s1.push({
                    'x': k*x0 + (1 - k)*x, 
                    'y': k*y0 + (1 - k)*y
                });
            }
        }
    }
    else { x0 = x; y0 = y; }
    xp = x; yp = y;
}
star = star.concat(s1);
/* HEART */
for(var i = 0; i < data.nr_heart; i++) {
    a = i*data.ba_heart + data.aoff_heart;
    x = -data.xo_heart + data.r_heart*cos(a);
    y = data.yo_heart + data.r_heart*sin(a);
    h1.push({ 'x' : x, 'y': y});
    a = (i + 1)*data.ba_heart - data.aoff_heart;
    x = data.xo_heart + data.r_heart*cos(a);
    y = data.yo_heart + data.r_heart*sin(a);
    h2.push({ 'x' : x, 'y': y});
}
h1.push({'x': 0, 'y': data.yu_heart});
heart = heart.concat(h1.concat(h2));
return [star, heart];
};
var setShape = function(el, points) {
var n = points.length, ptsstr = '';
for(var i = 0; i < n; i++) {
    ptsstr += points[i].x + ',' + points[i].y + ' ';
}
el.setAttribute('points', ptsstr.trim());
};
var getTimeline = function(endpoints, duration) {
var timeline = [], j, k, x, y, 
        start = endpoints[0], end = endpoints[1], 
        n = start.length;
for(var i = 0; i <= duration; i++) {
    k = .5*(1 - cos(i/duration*PI));
    timeline.push([]);
    for(var j = 0; j < n; j++) {
        x = round((1 - k)*start[j].x + k*end[j].x);
        y = round((1 - k)*start[j].y + k*end[j].y);
        timeline[i].push({'x': x, 'y': y});
    }
}
return timeline;
};
var getShade = function(v, v2, k) {
var mix = [], k = k || 0;
for(var i = 0; i < 3; i++) {
    mix[i] = (v2)?round((1 - k)*v[i] + k*v2[i]):v[i];
}
return 'rgb(' + mix.join(',') + ')';
};
var setShade = function(el, rgbstr) {
el.setAttribute('fill', rgbstr);
};
var getShades = function(endshades, duration) {
var s = [];
for(var i = 0; i <= duration; i++) {
    k = .5*(1 - cos(i/duration*PI));
    s.push(getShade(endshades[0], endshades[1], k));
}
return s;
};
var ani = function() {
var f = pow(-1, (t_incr + 1)*.5), 
        ra = f*(1 - t/DURATION)*180;
rotor.setAttribute('transform', 'rotate(' + ra + ')');
setShape(morpher, tl[t]);
setShade(morpher, shades[t]);
t += t_incr;
if(t < 0 || t > DURATION) {
    t_incr *= -1;
    t += t_incr;
    cancelAnimationFrame(rid);
    rid = null;
    return;
}
rid = requestAnimationFrame(ani);
};
tl = getTimeline(getEndpoints(getData(PRECISION, RC_PENTA, A_HEART)), DURATION);
shades = getShades(END_SHADES, DURATION);
rotor.setAttribute('transform', 'rotate(180)');
setShape(morpher, tl[0]);
setShade(morpher, shades[0]);
morpher.addEventListener('click', function(){
if(!rid) ani();
}, false);

如果有人能给我指出我失踪的地方,那就太好了。提前谢谢。

每次找到脚本标记时,浏览器都会在解析文档的其余部分之前运行它。因此,当您的javascript代码运行时,rotor元素还不存在,这就是它为null的原因。

script标记移动为body中的最后一个元素,代码就会运行。

根据经验,请始终将脚本放在正文末尾(</body>之前),以提高渲染速度。