问候专家和其他程序员......
我用 d3.js 做了一些实验,在这里找到了一个很好的动画模拟时钟示例:
http://www.google.de/url?sa=t&rct=j&q=d3%20analog%20clock&source=web&cd=1&cad=rja&ved=0CDIQFjAA&url=http%3A%2F%2Fwww.ericbullington.com%2Farticles%2F2012%2F10%2F27%2Fd3-oclock&ei=NNgIUuCqKomsOKmDgMAK&usg=AFQjCNGoI2g7XQIguM_6UM5V_6WzeJyPxA&bvm=bv.50500085,d.bGE
我把它改成了4个时钟,同时显示当地时间、伦敦、纽约和香港时间……
代码(片段)如下所示:
测试.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HEAD>
<META content="IE=10.000" http-equiv="X-UA-Compatible">
<META charset="utf-8">
<META http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<META name="viewport" content="width=device-width, initial-scale=1">
<SCRIPT src="d3.v2.min.js"></SCRIPT>
<SCRIPT src="clock.js"></SCRIPT>
</HEAD>
<BODY>
<DIV class="herechart"></DIV>
<DIV class="londonchart"></DIV>
<DIV class="newyorkchart"></DIV>
<DIV class="hongkongchart"></DIV>
<SCRIPT src="clock.js"></SCRIPT>
</BODY></HTML>
clock.js(修订):
(function() {
var clockGroup, fields, formatHour, formatMinute, formatSecond, height, offSetX, offSetY, pi, render, scaleHours, scaleSecsMins, vis, width;
formatSecond = d3.time.format("%S");
formatMinute = d3.time.format("%M");
formatHour = d3.time.format("%H");
herefields = function() {
var d, data, hour, minute, second;
d = new Date();
second = d.getSeconds();
minute = d.getMinutes();
hour = d.getHours() + minute / 60;
return data = [
{ "unit": "seconds", "text": formatSecond(d), "numeric": second },
{ "unit": "minutes", "text": formatMinute(d), "numeric": minute },
{ "unit": "hours", "text": formatHour(d), "numeric": hour }
];
};
londonfields = function() {
// fields creating in the same way as in herfields function
};
newyorkfields = function() {
// you get the idea
};
hongkongfields ) = function {
// i did it again
};
width = 82;
height = 82;
offSetX = 82;
offSetY = 82;
pi = Math.PI;
scaleSecsMins = d3.scale.linear().domain([0, 59 + 59 / 60]).range([0, 2 * pi]);
scaleHours = d3.scale.linear().domain([0, 11 + 59 / 60]).range([0, 2 * pi]);
// creating local clock frame
vis = d3.selectAll(".herechart").append("svg:svg").attr("width", width).attr("height", height);
clockGroup = vis.append("svg:g").attr("transform", "translate(" + offSetX + "," + offSetY + ")");
// creating London time clock frame
londonvis = d3.selectAll(".londonchart").append("svg:svg").attr("width", width).attr("height", height);
londonGroup = londonvis.append("svg:g").attr("transform", "translate(" + 260 + "," + -4 + ")");
// omitting creation of the two other clock frames
// ommitting creation of clock hands (using .append(...)) and texts alltogether - see web example
// render function
render = function(heredata, londondata, newyorkdata, hongkongdata) {
var hourArc, minuteArc, secondArc;
clockGroup.selectAll(".clockhand").remove();
londonGroup.selectAll(".clockhand").remove();
newyorkGroup.selectAll(".clockhand").remove();
hongkongGroup.selectAll(".clockhand").remove();
secondArc = d3.svg.arc().innerRadius(0).outerRadius(70).startAngle(function(d) { return scaleSecsMins(d.numeric); }).endAngle(function(d) { return scaleSecsMins(d.numeric); });
minuteArc = d3.svg.arc().innerRadius(0).outerRadius(66).startAngle(function(d) { return scaleSecsMins(d.numeric); }).endAngle(function(d) { return scaleSecsMins(d.numeric); });
hourArc = d3.svg.arc().innerRadius(0).outerRadius(50).startAngle(function(d) { return scaleHours(d.numeric % 12); }).endAngle(function(d) { return scaleHours(d.numeric % 12); });
clockGroup.selectAll(".clockhand").data(heredata).enter().append("svg:path").attr("d", function(d) { if (d.unit === "seconds") { return secondArc(d); } else if (d.unit === "minutes") { return minuteArc(d); } else if (d.unit === "hours") { return hourArc(d); }
}).attr("class", "clockhand").attr("stroke", "black").attr("stroke-width", function(d) { if (d.unit === "seconds") { return 1; } else if (d.unit === "minutes") { return 3; } else if (d.unit === "hours") { return 3; } }).attr("fill", "none");
londonGroup.selectAll(".clockhand").data(londondata).enter().append("svg:path").attr("d", function(d) { if (d.unit === "seconds") { return secondArc(d); } else if (d.unit === "minutes") { return minuteArc(d); } else if (d.unit === "hours") { return hourArc(d); }
}).attr("class", "clockhand").attr("stroke", "black").attr("stroke-width", function(d) { if (d.unit === "seconds") { return 1; } else if (d.unit === "minutes") { return 3; } else if (d.unit === "hours") { return 3; } }).attr("fill", "none");
newyorkGroup.selectAll(".clockhand").data(newyorkdata).enter().append("svg:path").attr("d", function(d) { if (d.unit === "seconds") { return secondArc(d); } else if (d.unit === "minutes") { return minuteArc(d); } else if (d.unit === "hours") { return hourArc(d); }
}).attr("class", "clockhand").attr("stroke", "black").attr("stroke-width", function(d) { if (d.unit === "seconds") { return 1; } else if (d.unit === "minutes") { return 3; } else if (d.unit === "hours") { return 3; } }).attr("fill", "none");
hongkongGroup.selectAll(".clockhand").data(hongkongdata).enter().append("svg:path").attr("d", function(d) { if (d.unit === "seconds") { return secondArc(d); } else if (d.unit === "minutes") { return minuteArc(d); } else if (d.unit === "hours") { return hourArc(d); }
}).attr("class", "clockhand").attr("stroke", "black").attr("stroke-width", function(d) { if (d.unit === "seconds") { return 1; } else if (d.unit === "minutes") { return 3; } else if (d.unit === "hours") { return 3; } }).attr("fill", "none");
};
// end of render function
// periodically getting time fields and give them to render function
setInterval(function() {
var data;
heredata = herefields();
londondata = londonfields();
newyorkdata = newyorkfields();
hongkongdata = hongkongfields();
return render(heredata, londondata, newyorkdata, hongkongdata);
}, 1000); }).call(this);
该代码对我来说很好用。
但我很想将它包含在我的一个 three.js 项目中,我在一个投影中使用两个具有两个不同渲染器(一个画布,一个 css3d 渲染器)的场景。我在那里做了很多飞行和旋转...... :-)
由于 D3 对象是 DIV,我想我可以创建 CSS3D 渲染的对象并将它们(TWEENING 和改变位置)与其他对象一起飞行。
有没有办法做到这一点?以及如何做到这一点。
下面,我展示了我在我的 three.js 项目中使用的一些代码,其中有一个 init() 函数,它创建 DIV 和场景、渲染器和投影......我在设计粒子和 DIV 以及很多在为它们设置动画的同时更改这些元素的东西......下面的代码效果很好(不是片段,而是完整的代码)。但是我该如何组合它们呢?
<body onload="connameinit();">
<script src="build/three.min.js"></script>
<script src="js/renderers/CSS3DRenderer.js"></script>
<script src="js/libs/tween.min.js"></script>
<script>
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 1000;
scene = new THREE.Scene();
var program = function ( context ) {
myindex++;
context.beginPath();
context.rect( 3, 12, 7, 1);
context.drawImage(backgroundImage01, 0, 0);
context.closePath();
context.fill();
}
group = new THREE.Object3D();
scene.add( group );
for ( var i = 0; i < 400; i++ ) {
particle = new THREE.Particle( new THREE.ParticleCanvasMaterial( { map: new THREE.Texture( generateSprite() ), color: Math.random() * 0x808008 + 0x808080, program: program } ) );
particle.position.x = Math.random() * 6000 - 3000;
particle.position.y = Math.random() * 6000 - 3000;
particle.position.z = Math.random() * 6000 - 5500;
particle.scale.x = particle.scale.y = Math.random() * 3 + 2;
initParticle( particle, i * 10 );
group.add( particle );
myparticles.push( particle );
}
renderer = new THREE.CanvasRenderer();
renderer.setClearColor(0x000000, 1);
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// creating the CSS3D rendered object
scene2 = new THREE.Scene();
var element = document.createElement( 'div' );
element.className = 'element';
element.style.width = Math.floor(window.innerWidth / window.innerHeight * 1400) + 'px';
element.style.height = '1400px';
element.style.backgroundColor = 'rgba(0,127,127,' + ( Math.random() * 0.5 + 0.25 ) + ')';
var profile = document.createElement( 'div' );
profile.className = 'profile';
profile.textContent = "";
element.appendChild( profile );
myimgdiv = new THREE.CSS3DObject( element );
myimgdiv.position.x = 0;
myimgdiv.position.y = 0;
myimgdiv.position.z = 0;
scene2.add( myimgdiv );
renderer2 = new THREE.CSS3DRenderer();
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
document.body.appendChild( renderer2.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
TWEEN.update();
camera.lookAt( scene.position );
mypindex = mypindex + mypmul;
if (mypindex > 500) {
mymulti = - mymulti;
mypmul = -1;
}
if (mypindex < -500) {
mymulti = - mymulti;
mypmul = 1;
}
group.rotation.x += mymulti * 0.0003;
group.rotation.y += mymulti * 0.0006;
myimgdiv.scale.x += mymulti * 0.0001;
myimgdiv.scale.y += mymulti * 0.0001;
renderer.render( scene, camera );
renderer2.render( scene2, camera );
}
function mydivtransform( targets, duration ) {
var object = myimgdiv;
var target = targets[ 0 ];
new TWEEN.Tween( object.position )
.to( { x: target.position.x, y: target.position.y, z: object.position.z }, duration )
.easing( TWEEN.Easing.Exponential.InOut )
.start();
}
</script>
</body>
</html>
我可以在 init() 循环中创建时钟 DIV,而不是将代码放在文档正文中吗?然后我会以某种方式拆分clock.js代码并将其一部分放入init()循环中,但是有人可以帮我吗?不过,我认为最好的方法是使用第三个渲染器(CSS3D),使用相同的投影仪来创建第三个场景。但是如何从 D3 对象创建 Three.js 混搭?当这些 Three.js 对象被移动或 TWEENed 时,我如何确保时钟指针的动画继续?
预先感谢您的所有帮助!
奥利弗