エキスパートと仲間のプログラマーに挨拶...
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つの時計に変更しました...
コード (スニペット) は次のようになります。
test.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);
そのコードは私にとってはうまくいきます。
しかし、それを 1 つのプロジェクションで 2 つの異なるレンダラー (1 つのキャンバス、1 つの css3d レンダラー) を持つ 2 つのシーンを使用している私の three.js プロジェクトに含めたいと思います。私はそこでたくさん飛んだり、回転したりしています... :-)
D3 オブジェクトは DIV であるため、CSS3D でレンダリングされたオブジェクトを作成し、それらを他のオブジェクトと一緒に (TWEENING および位置の変更) 飛び回らせることができると考えました。
それを行う方法はありますか?そして、これはどのように行うことができますか。
以下に、私の three.js プロジェクトで使用しているコードの一部を示します。このコードには、DIV とシーン、レンダラー、プロジェクションを作成する init() 関数があります。それらをアニメーション化しながらこれらの要素を変更するためのもの....以下のコードは非常にうまく機能します(スニペットではなく、完全なコード)。しかし、どうすればそれらを組み合わせることができますか?
<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() ループ内に配置しますが、誰かがそれを手伝ってくれませんか? ただし、同じプロジェクターを使用して、3 番目のレンダラー (CSS3D) を使用して 3 番目のシーンを作成するのが最善の方法です。しかし、D3 オブジェクトから Three.js マッシュを作成するにはどうすればよいでしょうか? また、これらの Three.js オブジェクトが移動または TWEEN されている間、時計の針のアニメーションが継続されるようにするにはどうすればよいでしょうか?
よろしくお願いいたします。
オリバー