Update: JSFiddle: https://jsfiddle.net/Qanary/915fg6ka/
I am trying to make my curveText function work (see bottom of this post). It normally works with fabric.js 1.2.0 however when I updated to fabric.js 1.7.9, the curving function locates the text in wrong positions when below two actions executed sequentially.
ACTIONS : - ISSUE 1
-text group scale is changed (I mean dragging the corner points by mouse to change size).
-setText called
fabric js 1.2.0:
fabric js 1.7.9
I debugged it and the reason for that is _updateObjectsCoords in fabricjs because when I removed it from the code and 2 actions I listed above works fine.
ISSUE 2:
But this time I have faced below problem which is group items are not correctly located when adding the text to canvas for the first time.
with _updateObjectsCoords
without _updateObjectsCoords
Here My Function:
var CurvedText = (function() {
function CurvedText( canvas, options ){
this.opts = options || {};
for ( var prop in CurvedText.defaults ) {
if (prop in this.opts) { continue; }
this.opts[prop] = CurvedText.defaults[prop];
}
this.canvas = canvas;
this.group = new fabric.Group([], {selectable: this.opts.selectable,radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse});
this.canvas.add( this.group ) ;
this.canvas.centerObject( this.group );
this.setText( this.opts.text );
this.canvas.setActiveObject( this.group );
this.canvas.getActiveObject().setCoords();
}
CurvedText.prototype.setObj = function(obj)
{
this.group=obj;
};
CurvedText.prototype.setText = function( newText ) {
this.opts.top=this.group.top;
this.opts.left=this.group.left;
while ( newText.length !== 0 && this.group.size() > newText.length ) {
this.group.remove( this.group.item( this.group.size()-1 ) );
}
for ( var i=0; i<newText.length; i++ ){
if ( this.group.item(i) === undefined ){
var letter = new fabric.Text(newText[i], {
selectable: true
});
this.group.add( letter );
}
else{
this.group.item(i).text = newText[i];
}
}
this.opts.text = newText;
this._setFontStyles();
this._render();
};
CurvedText.prototype._setFontStyles = function() {
for ( var i=0; i<this.group.size(); i++ ){
if( this.opts.textStyleName )
{
if( this.opts.textStyleName === 'fontFamily' )
{
this.group.item(i).setFontFamily( this.opts.fontFamily );
}
if( this.opts.textStyleName === 'fontColor' )
{
this.group.item(i).setFill( this.opts.fontColor );
}
}
else
{
this.group.item(i).setFontFamily( this.opts.fontFamily );
this.group.item(i).setFill( this.opts.fontColor );
}
this.group.item(i).setFontSize( this.opts.fontSize );
this.group.item(i).fontWeight = this.opts.fontWeight ;
}
};
CurvedText.prototype._render = function() {
var curAngle=0,angleRadians=0, align=0;
// Object may have been moved with drag&drop
if ( this.group.hasMoved() ) {
this.opts.top = this.group.top;
this.opts.left = this.group.left;
}
this.opts.angle = this.group.getAngle();
this.opts.scaleX = this.group.scaleX;
this.opts.scaleY = this.group.scaleY;
this.opts.radius = this.group.radiusVal;
this.opts.spacing = this.group.spacingVal;
this.opts.reverse = this.group.textFliping;
// Text align
if ( this.opts.align === 'center' ) {
align = ( this.opts.spacing / 2) * ( this.group.size() - 1) ;
} else if ( this.opts.align === 'right' ) {
align = ( this.opts.spacing ) * ( this.group.size() - 1) ;
}
for ( var i=0; i<this.group.size(); i++) {
// Find coords of each letters (radians : angle*(Math.PI / 180)
if ( this.opts.reverse ) {
curAngle = (-i * parseInt( this.opts.spacing, 10 )) + align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).setAngle( curAngle );
this.group.item(i).set( 'top', (Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (-Math.sin( angleRadians ) * this.opts.radius) );
} else {
curAngle = (i * parseInt( this.opts.spacing, 10)) - align;
angleRadians = curAngle * (Math.PI / 180);
this.group.item(i).setAngle( curAngle );
this.group.item(i).set( 'top', (-Math.cos( angleRadians ) * this.opts.radius) );
this.group.item(i).set( 'left', (Math.sin( angleRadians ) * this.opts.radius) ) ;
}
}
// Update group coords
this.group._calcBounds();
this.group._updateObjectsCoords();
this.group.top = this.opts.top;
this.group.left = this.opts.left;
this.group.saveCoords();
this.canvas.renderAll();
};
CurvedText.defaults = {
top: 0,
left: 0,
scaleX: 1,
scaleY: 1,
angle: 0,
spacing:0,
radius:0,
text: '',
align: 'center',
reverse:'',
fontSize:16,
fontWeight: 'normal',
selectable: true,
fontFamily:'',
fontColor:'black',
textStyleName:''
};
return CurvedText;
})();
This should do it, if I understood you correctly:
Just a small tweak to your updateText() function:
function updateText() {
var original = canvas.getActiveObject();
canvas.remove(original);
setText();
canvas.getActiveObject().set({
angle: original.angle,
top: original.top,
left: original.left,
scaleX: original.scaleX,
scaleY: original.scaleY
}).setCoords();
canvas.renderAll();
}
And finally, here's your all important JSFiddle updated, https://jsfiddle.net/rekrah/pkj82n4b/.
Update (v2)
- since you did plead in your bounty to make your function work, ;-).
Change this line:
this.group = new fabric.Group([], {selectable: this.opts.selectable,name:'arc',radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse,itemName:'text'});
To this:
this.group = new fabric.Group([], {selectable: this.opts.selectable,name:'arc',radiusVal:this.opts.radius,spacingVal:this.opts.spacing,textFliping:this.opts.reverse,itemName:'text',originX:'center',originY:'center'});
And to get it a little more esthetically pleasing you might want to...
Change this line: canvas = new fabric.Canvas('c',);
To this: canvas = new fabric.Canvas('c',{centeredScaling: true});
And here's your original Plunker updated again, https://jsfiddle.net/rekrah/c7cjzkfd/.
This leaves your updateText() function as you had it.
Let me know if you have any other questions. Always happy to help!
You can use this:https://github.com/EffEPi/fabric.curvedText you can see the demo
Related
I have recently started playing around with Threejs cars example at below URL:
https://threejs.org/examples/webgl_loader_ctm_materials.html
Fantastic piece to test realistic objects. I wanted to change materials for this car on runtime but I have been blocked due to the way that mesh is being added to the scene. I will appreciate someone can bail me out and post a fiddle or share code.
Here is how the mesh is added to the scene:
var loader = new THREE.CTMLoader();
loader.loadParts( "catalog/view/javascript/models/ctm/camaro/camaro.js", function( geometries, materials ) {
hackMaterials( materials );
for ( var i = 0; i < geometries.length; i ++ ) {
var mesh = new THREE.Mesh( geometries[ i ], materials[ i ] );
mesh.position.copy( position );
mesh.scale.copy( scale );
scene.add( mesh );
}
Here is the hackMaterials(materials) function.
function hackMaterials( materials ) {
for ( var i = 0; i < materials.length; i ++ ) {
var m = materials[ i ];
if ( m.name.indexOf( "Body" ) !== -1 ) {
var mm = new THREE.MeshStandardMaterial( );
mm.color.setHex( 0x56cc5b ); //
mm.lightMap = m.map;
//mm.envMap = textureCube;
mm.metalness = 0.5;
mm.roughness = 0.3;
materials[ i ] = mm;
}
else if ( m.name.indexOf( "tire_car" ) !== -1 ) {
var mm = new THREE.MeshStandardMaterial();
mm.color.setHex( 0x000000 );
mm.lightMap = m.map;
mm.metalness = 0.1;
mm.roughness = 0.9;
materials[ i ] = mm;
}
else if ( m.name.indexOf( "mirror" ) !== -1 ) {
var mm = new THREE.MeshStandardMaterial();
mm.color.setHex( 0x808080 );
mm.lightMap = m.map;
mm.envMap = textureCube;
mm.metalness = 0.9;
mm.roughness = 0.5;
materials[ i ] = mm;
}
else if ( m.name.indexOf( "glass" ) !== -1 ) {
var mm = new THREE.MeshStandardMaterial();
mm.color.copy( m.color );
// mm.lightMap = m.map;
mm.envMap = textureCube;
mm.metalness = 1;
mm.roughtness = 0.1;
mm.opacity = m.opacity;
mm.transparent = true;
materials[ i ] = mm;
}
else if ( m.name.indexOf( "Material.001" ) !== -1 ) {
var mm = new THREE.MeshPhongMaterial( { map: m.map } );
mm.specularMap = m.map;
mm.shininess = 30;
mm.color.setHex( 0xffffff );
mm.metal = true;
materials[ i ] = mm;
}
materials[ i ].side = THREE.DoubleSide;
}
}
Needless to point out that function hackMaterials is looping through material names in an array and then based on the names, it is assigning different values for materials.
I have been trying to use dat.gui.js but only thing I have been able to do so far is to create a color control via this code and produce console output via below code:
var color = 0xffffff;
var params = {
modelcolor: "#ffffff"
};
var gui = new dat.GUI();
var folder = gui.addFolder('Model Colour');
folder.addColor(params, 'modelcolor')
.name('Model Color')
.onChange(function() {
//var mm = new THREE.MeshStandardMaterial( {color: params.modelcolor});
//alert(params.modelcolor)
color = params.modelcolor.replace("#", "0x");
//mm.color.setHex(0xdd5353);
console.log(color);
for ( var i = 0; i < geometries.length; i ++ ) {
//console.log(materials[i].name);
if (materials[i].name.indexOf("Plane") !== -1) {
materials[i].color.setHex(0x56cc5b);
console.log("color should be changed for " + materials[i].name);
}
}
It outputs the desired color code in console but does not apply it to the car.
That will be of great help if someone could post even a basic working example with a drop down color changer.
Thanks in advance
In THREE.js, whenever you update a material and you want the effect to be updated across the scene, you need to set the following flag on the material:
material.needsUpdate = true;
Did this solve your problem or are there some other issues?
I have a question about the topic.
I use stackover at the first time.
I use JS wookmark plugin. by the way I make web pages.
One of pages with sidebar with open and close.
When I close the left sidebar, It makes a space left of article.
Usually It resizes width on no space. The open sidebar size is 260px. The close size is 70.
I use these but no action.
$(document).ready(function() {
var article_list = $("#grid-container article").get();
var outer = $('<div class="grid-outer"></div>').get(0);
var nowbox = false;
for ( var i = 0; i < article_list.length; i++ ) {
if($(article_list[i]).hasClass('area')){
nowbox = false;
$(outer).append(article_list[i]);
}
if($(article_list[i]).hasClass('area-box')) {
if(!nowbox) {
nowbox = $('<div class="gridbox"></div>').get(0);
$(outer).append(nowbox);
}
$(nowbox).append(article_list[i]);
}
}
$("#grid-container").empty();
$("#grid-container").append(outer);
var options = {
offset: 20, // Optional, the distance between grid items
autoResize: true,
fillEmptySpace: true,
};
var resizeTimer = null;
var gridarr = [];
var gridboxlist = $('.gridbox').get();
for ( var i = 0; i < gridboxlist.length; i++ ) {
gridarr[i] = new Wookmark( gridboxlist[i], options);
}
resize();
resizeTimer = setTimeout(function() {
resize();
}, 0);
$(window).resize(function(){
clearTimeout(resizeTimer);
resize();
resizeTimer = setTimeout(function() {
resize();
}, 0);
})
function resize(){
var gridboxlist = $('.gridbox').get();
$(gridboxlist).each(function(){
var window_w = window.outerWidth;
var outer_w = $(this).width();
if( window_w < 1400) {
var w = Math.floor((( outer_w - ( 20 * 1 )) / 2));
$(this).find('.area-box').css({
'width': w+'px'
});
} else {
var w = Math.floor((( outer_w - ( 20 * 2 )) / 3));
$(this).find('.area-box').css({
'width': w+'px'
});
}
});
if( 0 < gridarr.length ){
refresh();
}
}
function refresh(){
for ( var i = 0; i < gridarr.length; i++ ) {
gridarr[i].layout(true);
}
}
});
I found this example that works for physics.js 0.6.0 http://jsfiddle.net/REGCU/22/
but I cannot get it to work with 0.7.0 http://jsfiddle.net/REGCU/23/
javascript:
Physics(function (world) {
var viewWidth = window.innerWidth
,viewHeight = window.innerHeight
// bounds of the window
,viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight)
,edgeBounce
,renderer
;
// create a renderer
renderer = Physics.renderer('canvas', {
el: 'viewport'
,width: viewWidth
,height: viewHeight
});
// add the renderer
world.add(renderer);
// render on each step
world.on('step', function () {
world.render();
});
// constrain objects to these bounds
edgeBounce = Physics.behavior('edge-collision-detection', {
aabb: viewportBounds
,restitution: 0.2
,cof: 1
});
var gravity = Physics.behavior('constant-acceleration', {
acc: { x : 0, y: 0.0004 } // this is the default: .0004
});
// resize events
window.addEventListener('resize', function () {
viewWidth = window.innerWidth;
viewHeight = window.innerHeight;
renderer.el.width = viewWidth;
renderer.el.height = viewHeight;
viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight);
// update the boundaries
edgeBounce.setAABB(viewportBounds);
}, true);
// for constraints
var rigidConstraints = Physics.behavior('verlet-constraints', {
iterations: 10
});
// the "basket"
var basket = [];
var fpos = window.innerWidth / 2;
var epos = window.innerHeight / 2;
for ( var i = fpos; i < fpos + epos; i += 5 ){
l = basket.push(
Physics.body('circle', {
x: i
,y: 50 - (i-fpos)
,radius: 1
,restitution: 0
,mass: 1000
,conf: 1
,hidden: true
})
);
rigidConstraints.distanceConstraint( basket[ l - 1 ], basket[ l - 2 ], 2 );
}
var box = Physics.body('rectangle', {
x: i
,y: 50 - (i-fpos)
,width: 60
,height: 60
,styles: { fillStyle: '#fff' }
});
rigidConstraints.distanceConstraint( basket[ l - 1 ], box, 2 );
world.add(box);
world.on('render', function( data ){
var renderer = data.renderer;
for ( var i = 1, l = basket.length; i < l; ++i ){
renderer.drawLine(basket[ i - 1 ].state.pos, basket[ i ].state.pos, {
strokeStyle: '#ccc'
,lineWidth: 5
,restitution: 0
,mass: 1000
,conf: 1
});
}
});
// fix the ends
basket[ 0 ].treatment = 'static';
world.add( basket );
world.add( rigidConstraints );
// add things to the world
world.add([
Physics.behavior('interactive', { el: renderer.el })
,Physics.behavior('constant-acceleration')
,Physics.behavior('body-impulse-response')
// ,Physics.behavior('body-collision-detection')
,Physics.behavior('sweep-prune')
,edgeBounce
,gravity
]);
// subscribe to ticker to advance the simulation
Physics.util.ticker.on(function( time ) {
world.step( time );
});
// start the ticker
Physics.util.ticker.start();
});
body{
background: #1d1d1d;
margin: 0;
padding: 0;
}
<script src="http://wellcaffeinated.net/PhysicsJS/assets/scripts/vendor/physicsjs-current/physicsjs-full.js"></script>
and I get no error messages (just nothing happens on the output).
I have also been able to run the 0.6.0 version on my computer, but had similar non-results for the 0.7.0 version.
Any ideas on what I need to change?
I'm trying to move my slideshow function runShow() into a seperate .js file named panzoomslideshow.js
This is simply to separate my script into another file that is then used by all my pages.
I can get the resize trigger to fire an alert, but it won't call the runShow () function - what am I doing wrong? I got it to run before, but now I can't!
The script to call panzoomslideshow.js in the head of my web page and this is where on each resize, the runShow() function in the panzoomslideshow.js file function is called:
<script type="text/javascript"> //*** This will reload the player upon resizing! ***\\
var resizeTimer;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(runShow(), 100);
});
</script>
I should note I also tried putting the $(function(){ }) around it, but then all the variables can't be accessed from the runShow() function which won't run...
panzoomslideshow.js ->
var dur = 2000;
var pDur = 4500;
var vp_width = window.innerWidth;
var vp_height = window.innerHeight;
var width_large = 880;
var height_large = 495;
var width_medium = 720;
var height_medium = 405;
var width_small = 480;
var height_small = 270;
var width_micro = 320;
var height_micro = 180;
var slide_width;
var slide_height;
var anim_width;
var anim_height;
var margin_top;
var margin_left;
alert("The Global variables are set, like vp_width and vp_height are "+vp_width+" and "+vp_height);
runShow();
function runShow() {
if(vp_width <= 320){ //SET Micro size
slide_width = width_micro;
slide_height = height_micro;
anim_width = (width_micro * 1.2);
anim_height = (height_micro * 1.2);
margin_top = -30;
margin_left = -60;
} else if(vp_width <= 480){ //SET small size
slide_width = width_small;
slide_height = height_small;
anim_width = (width_small * 1.2);
anim_height = (height_small * 1.2);
margin_top = -70;
margin_left = -150;
} else if(vp_width <= 1140){ //SET Medium size
slide_width = width_medium;
slide_height = height_medium;
anim_width = (width_medium * 1.2);
anim_height = (height_medium * 1.2);
margin_top = -80;
margin_left = -180;
} else if(vp_width <= 1400){ //SET Large size
slide_width = width_large;
slide_height = height_large;
anim_width = (width_large * 1.2);
anim_height = (height_large * 1.2);
margin_top = -100;
margin_left = -200;
} else {
//do nothing since the screen size is too small???
}
alert("runShow() is invoked! Slideshow Width and Height will be "+slide_width+" and "+slide_height+" The Global variables are set, like vp_width and vp_height are "+vp_width+" and "+vp_height);
$(".carousel").carouFredSel({
items: {
visible: 1,
width: slide_width,
height: slide_height
},
scroll: {
fx: "fade",
easing: "linear",
duration: dur,
timeoutDuration: pDur,
onBefore: function( data ) {
animate( data.items.visible, pDur + ( dur * 3 ) );
},
onAfter: function( data ) {
data.items.old.find( "img" ).stop().css({
width: slide_width,
height: slide_height,
marginTop: 0,
marginLeft: 0
});
}
},
onCreate: function( data ) {
animate( data.items, pDur + ( dur *2 ) );
}
});
function animate( item, dur ) {
var obj = {
width: anim_width,
height: anim_height
};
switch( Math.ceil( Math.random() * 2 ) ) {
case 1:
obj.marginTop = 0;
break;
case 2:
obj.marginTop = -80
break;
}
switch( Math.ceil( Math.random() * 2 ) ) {
case 1:
obj.marginLeft = 0;
break;
case 2:
obj.marginLeft = -170
break;
}
item.find( "img" ).animate(obj, dur, "linear" );
}
};
:)
Did you try this?
$(document).ready(function () {
//your javascript code
});
Greetings experts and fellow programmers...
I experimented a bit with d3.js and I found a nice example for an animated analog clock here:
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
I changed it into 4 clocks, showing local time, London, New York and Hong Kong time simultaneously...
The code (snippet) looks like this:
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 (revised):
(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);
That code work well for me.
But I would LOVE to include that into a three.js project of mine, where I am using two scenes with two different renderers (one canvas, one css3d renderer) in one projection. I am doing a lot of flying and rotatin' around there... :-)
As the D3 objects are DIVs, I thought I can create CSS3D-rendered objects and fly them (TWEENING and changing positions) around with the other objects.
Is there a way to do it? And how can this be done.
Below, I show some of the code that I am using in my three.js project where there is an init() function which CREATES DIVs and scene,renderers and projections... I cut out heavily on designing particles and DIVs plus alot of stuff for changing these elements while animating them.... the code below works very well (not the snippet, but the full code). But how do I combine them?
<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>
Can I create the clock DIVs in the init() loop instead of placing the code inside the body of the document. I would then somehow split the clock.js code and put part of it within the init() loop, but could somebody help me with that? I though, best way would be a third scene, using a third renderer (CSS3D), using the same projector.
But how can I create Three.js mashes from the D3 objects?
And how can I make sure that the animation of the clock hands continues while these Three.js objects are moved or TWEENed?
Thank you in advance for all your help!
Oliver