1

エキスパートと仲間のプログラマーに挨拶...

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 されている間、時計の針のアニメーションが継続されるようにするにはどうすればよいでしょうか?

よろしくお願いいたします。

オリバー

4

0 に答える 0