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

标签 javascript jquery html css svg

我在 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元素尚不存在,这就是它为空的原因。

移动您的 script标记为 body 中的最后一个元素并且代码应该运行。

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

关于javascript - 使用 css 和 javascript 调整 svg 动画时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34360895/

相关文章:

javascript - 如何隐藏用Javascript编写的敏感数据?

javascript - 我对 call() 感到困惑,为什么我的代码不起作用?

javascript - 检查 2 个变量是否包含完全相同的文本并使用 jquery 执行操作

Javascript 数组未加入 | (或)字符

html - 将溢出设置为在固定的 div 上滚动不起作用

python - 如何使用beautifulsoup获取html中的类内容?

javascript - Azure 移动服务 Javascript 库和更新 - 无法读取方法

javascript - 在 onclick 事件中设置 css 属性

javascript - jquery .autocomplete 仅显示集合中的最后一条记录

javascript - 我们可以使用 jquery 将选择从一个页面转移到另一个页面吗