3D Sphere _wonder Follow 2010-08-25 12:25:44 License: MIT License Fork14 Fav24 View10268 Play Stop Reload Fullscreen Smart Phone Fork tree Readme JavaScript 347 lines HTML 2 lines CSS 1 lines 3D Sphere // クリックするとワイヤーのみになります。 /* ------ Stage Class ------------------------------------------*/ var Stage = function( id ){ this.id = id; this.canvas; this.timer; this.points = []; this.triangles = []; this.stageWidth = 445; this.stageHeight = 445; this.angleX = 0; this.angleY = 0; this.timerDelay = 33; this.renderFlag = true; this.init(); }; Stage.prototype = { init: function(){ var node = document.getElementById( this.id ); if(!node.getContext) return; this.canvas = node.getContext("2d"); Base.addevent( node, "mousemove", Base.getMousePos); Base.addevent( node, "click", Base.bind( this, this.onClick )); }, onClick: function(){ this.renderFlag = !this.renderFlag; }, start: function(){ this.enterFrame(); this.internal = setInterval( Base.bind( this, this.enterFrame ), this.timerDelay ); }, stop: function(){ clearInterval( this.internal ); }, setPoint: function( point ){ this.points = point; }, setTriangles: function( triangle ){ this.triangles.push( triangle ); }, enterFrame: function(){ for( var i = 0, n = this.points.length ; i < n; i++ ){ for( var j = 0, m = this.points[i].length; j < m; j++ ){ this.angleX += ( Base.mouseY - this.points[i][j].vpY ) * 0.00001; this.angleY += ( Base.mouseX - this.points[i][j].vpX ) * 0.00001; this.rotateX( this.points[i][j], this.angleX ); this.rotateY( this.points[i][j], this.angleY ); } } this.render(); }, rotateX: function( point, angle ){ cosX = Math.cos( angle ); sinX = Math.sin( angle ); y1 = point.cy * cosX - point.cz * sinX; z1 = point.cz * cosX + point.cy * sinX; point.y = y1; point.z = z1; }, rotateY: function( point, angle ){ cosY = Math.cos( angle ); sinY = Math.sin( angle ); x1 = point.cx * cosY - point.z * sinY; z1 = point.z * cosY + point.cx * sinY; point.x = x1; point.z = z1; }, render: function(){ this.canvas.clearRect( 0, 0, this.stageWidth, this.stageHeight ); this.canvas.save(); for( var i = 0, n = this.triangles.length; i < n; i++ ){ var triangle = this.triangles[i]; if( triangle.isBackFace() ){ continue; }; var color = triangle.getAdjustedColor(); this.canvas.beginPath(); this.canvas.fillStyle = color; this.canvas.strokeStyle = this.renderFlag ? color : "#cc0000"; this.canvas.lineWidth = 2; this.canvas.lineJoin = "round"; this.canvas.moveTo( triangle.a.screenX(), triangle.a.screenY() ); this.canvas.lineTo( triangle.b.screenX(), triangle.b.screenY() ); this.canvas.lineTo( triangle.c.screenX(), triangle.c.screenY() ); this.canvas.lineTo( triangle.a.screenX(), triangle.a.screenY() ); this.canvas.closePath(); if( this.renderFlag ) this.canvas.fill(); this.canvas.stroke(); } this.sortZ(); this.canvas.restore(); }, sortZ: function(){ this.triangles.sort( function(a, b){ return ( b.depth() - a.depth() ); } ); } }; /* ------ Point3D Class ------------------------------------------*/ var Point3D = function( posX, posY, posZ ){ this.x = posX; this.y = posY; this.z = posZ; this.cx = posX; this.cy = posY; this.cz = posZ; this.centerX = 0; this.centerY = 0; this.centerZ = 0; this.fl = 250; this.vpX = 0; this.vpY = 0; }; Point3D.prototype = { setVanishingPoint: function( vpX, vpY ){ this.vpX = vpX; this.vpY = vpY; }, setCenter: function( centerX, centerY, centerZ ){ this.centerX = centerX; this.centerY = centerY; this.centerZ = centerZ; }, screenX: function(){ return this.vpX + this.centerX + this.x * this.getScale(); }, screenY: function(){ return this.vpY + this.centerY + this.y * this.getScale(); }, getScale: function(){ return this.fl / ( this.fl + this.z + this.centerZ ); } }; /* ------ Triangle Class ------------------------------------------*/ var Triangle = function( pointA, pointB, pointC, color ){ this.a = pointA; this.b = pointB; this.c = pointC; this.color = color; this.light; }; Triangle.prototype = { depth: function(){ var posZ = Math.min( this.a.z, this.b.z ); posZ = Math.min( posZ, this.c.z ); return posZ; }, isBackFace: function(){ var cax = this.c.screenX() - this.a.screenX(); var cay = this.c.screenY() - this.a.screenY(); var bcx = this.b.screenX() - this.c.screenX(); var bcy = this.b.screenY() - this.c.screenY(); return cax * bcy > cay * bcx; }, getAdjustedColor: function(){ var color = parseInt( '0x'+( this.color.charAt(0) == "#" ? this.color.substring(1) : this.color ) ); var red = ( color & 0xff0000 ) >> 16; var green = ( color & 0x00ff00 ) >> 8; var blue = ( color & 0x0000ff ); var lightFactor = this.getLightFactor(); red *= lightFactor; green *= lightFactor; blue *= lightFactor; color = red << 16 | green << 8 | blue ; return "#" + color.toString(16); }, getLightFactor: function(){ var ab = new Object(); ab.x = this.a.x - this.b.x; ab.y = this.a.y - this.b.y; ab.z = this.a.z - this.b.z; var bc = new Object(); bc.x = this.b.x - this.c.x; bc.y = this.b.y - this.c.y; bc.z = this.b.z - this.c.z; var norm = new Object(); norm.x = ( ab.y * bc.z ) - ( ab.z * bc.y ); norm.y = -(( ab.x * bc.z ) - ( ab.z * bc.x )); norm.z = ( ab.x * bc.y ) - ( ab.y * bc.x ); var dotProd = norm.x * this.light.x + norm.y * this.light.y + norm.z * this.light.z; var normMag = Math.sqrt( norm.x * norm.x + norm.y * norm.y + norm.z * norm.z ); var lightMag = Math.sqrt( this.light.x * this.light.x + this.light.y * this.light.y + this.light.z * this.light.z ); return ( Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * this.light.brightness; } }; /* ------ Light Class ------------------------------------------*/ var Light = function( posX, posY, posZ, brightness ){ this.x = -100; this.y = -100; this.z = -100; this.brightness = 1; if( arguments[0] ) this.x = posX; if( arguments[1] ) this.y = posY; if( arguments[2] ) this.z = posZ; if( arguments[3] ) this.brightness = brightness; }; Light.prototype = { setBrightness: function( num ){ this.brightness = Math.max( num, 0 ); this.brightness = Math.min( this.brightness, 1 ); } }; /* ------ Base Class ------------------------------------------*/ var Base = { mouseX: 0, mouseY: 0, getMousePos: function( e ){ var obj = new Object(); if( document.all ){ Base.mouseX = event.x + document.body.scrollLeft; Base.mouseY = event.y + document.body.scrollTop; } else { Base.mouseX = e.pageX; Base.mouseY = e.pageY; } return obj; }, addevent: function(node,evt,func){ if(node.addEventListener){ node.addEventListener(evt,func,false); } else if(node.attachEvent){ node.attachEvent("on"+evt,func); } }, bind: function(){ var args=[]; if(arguments){ for(var i=0,n=arguments.length;i<n;i++){ args.push(arguments[i]); } } var object=args.shift(); var func=args.shift(); return function(event) { return func.apply(object,[event||window.event].concat(args)); } } }; /* ------ Client ------------------------------------------*/ (function(){ window.onload = function(){ var stage = new Stage("canvas"); var lat = 24; var lang = 16; var radius = 100; var color = "#cc0000"; var points = []; for( var i = 0; i < lat / 2 + 1; i++ ){ points[i] = new Array(); if( i == 0 ){ points[i][0] = new Point3D( 0, -radius, 0 ); } else if( i == lat/2 ){ points[i][0] = new Point3D( 0, radius, 0 ); } else { var cos = Math.cos( Math.PI * 2 / lat * i ); var sin = Math.sin( Math.PI * 2 / lat * i ); var x1 = points[0][0].cx * cos - points[0][0].cy * sin; var y1 = points[0][0].cy * cos + points[0][0].cx * sin; points[i][0] = new Point3D( x1, y1, 0 ); for( var j = 1; j < lang; j++ ){ var cos = Math.cos( Math.PI * 2 / lang * j ); var sin = Math.sin( Math.PI * 2 / lang * j ); var x1 = points[i][0].cx * cos - points[i][0].cz * sin; var z1 = points[i][0].cz * cos + points[i][0].cx * sin; points[i][j] = new Point3D( x1, y1, z1 ); } } } for( i = 0; i < points.length; i++ ){ for( j = 0; j < points[i].length; j++ ){ var point = points[i][j]; point.setVanishingPoint( stage.stageWidth / 2, stage.stageHeight / 2 ); point.setCenter( 0, 0, 50); } } stage.setPoint( points ); //set Triangle for( i = 0, n = points.length - 1; i < n; i++ ){ var pArray = points[i]; var pArray2 = points[i+1]; if( pArray.length == 1 ){ for( j = 0, m = pArray2.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[0], pArray2[j+1], pArray2[j], color ) ); } stage.setTriangles( new Triangle( pArray[0], pArray2[0], pArray2[pArray2.length-1], color ) ); } else if( pArray2.length == 1 ){ for( j = 0, m = pArray.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[j], pArray[j+1], pArray2[0], color ) ); } stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray[0], pArray2[0], color ) ); } else { for( j = 0, m = pArray.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[j], pArray2[j+1], pArray2[j], color ) ); stage.setTriangles( new Triangle( pArray[j], pArray[j+1], pArray2[j+1], color ) ); } stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray2[0], pArray2[pArray.length-1], color ) ); stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray[0], pArray2[0], color ) ); } } // set lights var triangles = stage.triangles; var light = new Light(); for( i = 0; i < triangles.length; i++ ){ triangles[i].light = light; } stage.start(); }})(); <canvas id='canvas' width="445" height="445"></canvas> 3D Sphere body { background-color: #ffffff; font: 30px sans-serif; } // クリックするとワイヤーのみになります。 /* ------ Stage Class ------------------------------------------*/ var Stage = function( id ){ this.id = id; this.canvas; this.timer; this.points = []; this.triangles = []; this.stageWidth = 445; this.stageHeight = 445; this.angleX = 0; this.angleY = 0; this.timerDelay = 33; this.renderFlag = true; this.init(); }; Stage.prototype = { init: function(){ var node = document.getElementById( this.id ); if(!node.getContext) return; this.canvas = node.getContext("2d"); Base.addevent( node, "mousemove", Base.getMousePos); Base.addevent( node, "click", Base.bind( this, this.onClick )); }, onClick: function(){ this.renderFlag = !this.renderFlag; }, start: function(){ this.enterFrame(); this.internal = setInterval( Base.bind( this, this.enterFrame ), this.timerDelay ); }, stop: function(){ clearInterval( this.internal ); }, setPoint: function( point ){ this.points = point; }, setTriangles: function( triangle ){ this.triangles.push( triangle ); }, enterFrame: function(){ for( var i = 0, n = this.points.length ; i < n; i++ ){ for( var j = 0, m = this.points[i].length; j < m; j++ ){ this.angleX += ( Base.mouseY - this.points[i][j].vpY ) * 0.00001; this.angleY += ( Base.mouseX - this.points[i][j].vpX ) * 0.00001; this.rotateX( this.points[i][j], this.angleX ); this.rotateY( this.points[i][j], this.angleY ); } } this.render(); }, rotateX: function( point, angle ){ cosX = Math.cos( angle ); sinX = Math.sin( angle ); y1 = point.cy * cosX - point.cz * sinX; z1 = point.cz * cosX + point.cy * sinX; point.y = y1; point.z = z1; }, rotateY: function( point, angle ){ cosY = Math.cos( angle ); sinY = Math.sin( angle ); x1 = point.cx * cosY - point.z * sinY; z1 = point.z * cosY + point.cx * sinY; point.x = x1; point.z = z1; }, render: function(){ this.canvas.clearRect( 0, 0, this.stageWidth, this.stageHeight ); this.canvas.save(); for( var i = 0, n = this.triangles.length; i < n; i++ ){ var triangle = this.triangles[i]; if( triangle.isBackFace() ){ continue; }; var color = triangle.getAdjustedColor(); this.canvas.beginPath(); this.canvas.fillStyle = color; this.canvas.strokeStyle = this.renderFlag ? color : "#cc0000"; this.canvas.lineWidth = 2; this.canvas.lineJoin = "round"; this.canvas.moveTo( triangle.a.screenX(), triangle.a.screenY() ); this.canvas.lineTo( triangle.b.screenX(), triangle.b.screenY() ); this.canvas.lineTo( triangle.c.screenX(), triangle.c.screenY() ); this.canvas.lineTo( triangle.a.screenX(), triangle.a.screenY() ); this.canvas.closePath(); if( this.renderFlag ) this.canvas.fill(); this.canvas.stroke(); } this.sortZ(); this.canvas.restore(); }, sortZ: function(){ this.triangles.sort( function(a, b){ return ( b.depth() - a.depth() ); } ); } }; /* ------ Point3D Class ------------------------------------------*/ var Point3D = function( posX, posY, posZ ){ this.x = posX; this.y = posY; this.z = posZ; this.cx = posX; this.cy = posY; this.cz = posZ; this.centerX = 0; this.centerY = 0; this.centerZ = 0; this.fl = 250; this.vpX = 0; this.vpY = 0; }; Point3D.prototype = { setVanishingPoint: function( vpX, vpY ){ this.vpX = vpX; this.vpY = vpY; }, setCenter: function( centerX, centerY, centerZ ){ this.centerX = centerX; this.centerY = centerY; this.centerZ = centerZ; }, screenX: function(){ return this.vpX + this.centerX + this.x * this.getScale(); }, screenY: function(){ return this.vpY + this.centerY + this.y * this.getScale(); }, getScale: function(){ return this.fl / ( this.fl + this.z + this.centerZ ); } }; /* ------ Triangle Class ------------------------------------------*/ var Triangle = function( pointA, pointB, pointC, color ){ this.a = pointA; this.b = pointB; this.c = pointC; this.color = color; this.light; }; Triangle.prototype = { depth: function(){ var posZ = Math.min( this.a.z, this.b.z ); posZ = Math.min( posZ, this.c.z ); return posZ; }, isBackFace: function(){ var cax = this.c.screenX() - this.a.screenX(); var cay = this.c.screenY() - this.a.screenY(); var bcx = this.b.screenX() - this.c.screenX(); var bcy = this.b.screenY() - this.c.screenY(); return cax * bcy > cay * bcx; }, getAdjustedColor: function(){ var color = parseInt( '0x'+( this.color.charAt(0) == "#" ? this.color.substring(1) : this.color ) ); var red = ( color & 0xff0000 ) >> 16; var green = ( color & 0x00ff00 ) >> 8; var blue = ( color & 0x0000ff ); var lightFactor = this.getLightFactor(); red *= lightFactor; green *= lightFactor; blue *= lightFactor; color = red << 16 | green << 8 | blue ; return "#" + color.toString(16); }, getLightFactor: function(){ var ab = new Object(); ab.x = this.a.x - this.b.x; ab.y = this.a.y - this.b.y; ab.z = this.a.z - this.b.z; var bc = new Object(); bc.x = this.b.x - this.c.x; bc.y = this.b.y - this.c.y; bc.z = this.b.z - this.c.z; var norm = new Object(); norm.x = ( ab.y * bc.z ) - ( ab.z * bc.y ); norm.y = -(( ab.x * bc.z ) - ( ab.z * bc.x )); norm.z = ( ab.x * bc.y ) - ( ab.y * bc.x ); var dotProd = norm.x * this.light.x + norm.y * this.light.y + norm.z * this.light.z; var normMag = Math.sqrt( norm.x * norm.x + norm.y * norm.y + norm.z * norm.z ); var lightMag = Math.sqrt( this.light.x * this.light.x + this.light.y * this.light.y + this.light.z * this.light.z ); return ( Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * this.light.brightness; } }; /* ------ Light Class ------------------------------------------*/ var Light = function( posX, posY, posZ, brightness ){ this.x = -100; this.y = -100; this.z = -100; this.brightness = 1; if( arguments[0] ) this.x = posX; if( arguments[1] ) this.y = posY; if( arguments[2] ) this.z = posZ; if( arguments[3] ) this.brightness = brightness; }; Light.prototype = { setBrightness: function( num ){ this.brightness = Math.max( num, 0 ); this.brightness = Math.min( this.brightness, 1 ); } }; /* ------ Base Class ------------------------------------------*/ var Base = { mouseX: 0, mouseY: 0, getMousePos: function( e ){ var obj = new Object(); if( document.all ){ Base.mouseX = event.x + document.body.scrollLeft; Base.mouseY = event.y + document.body.scrollTop; } else { Base.mouseX = e.pageX; Base.mouseY = e.pageY; } return obj; }, addevent: function(node,evt,func){ if(node.addEventListener){ node.addEventListener(evt,func,false); } else if(node.attachEvent){ node.attachEvent("on"+evt,func); } }, bind: function(){ var args=[]; if(arguments){ for(var i=0,n=arguments.length;i<n;i++){ args.push(arguments[i]); } } var object=args.shift(); var func=args.shift(); return function(event) { return func.apply(object,[event||window.event].concat(args)); } } }; /* ------ Client ------------------------------------------*/ (function(){ window.onload = function(){ var stage = new Stage("canvas"); var lat = 24; var lang = 16; var radius = 100; var color = "#cc0000"; var points = []; for( var i = 0; i < lat / 2 + 1; i++ ){ points[i] = new Array(); if( i == 0 ){ points[i][0] = new Point3D( 0, -radius, 0 ); } else if( i == lat/2 ){ points[i][0] = new Point3D( 0, radius, 0 ); } else { var cos = Math.cos( Math.PI * 2 / lat * i ); var sin = Math.sin( Math.PI * 2 / lat * i ); var x1 = points[0][0].cx * cos - points[0][0].cy * sin; var y1 = points[0][0].cy * cos + points[0][0].cx * sin; points[i][0] = new Point3D( x1, y1, 0 ); for( var j = 1; j < lang; j++ ){ var cos = Math.cos( Math.PI * 2 / lang * j ); var sin = Math.sin( Math.PI * 2 / lang * j ); var x1 = points[i][0].cx * cos - points[i][0].cz * sin; var z1 = points[i][0].cz * cos + points[i][0].cx * sin; points[i][j] = new Point3D( x1, y1, z1 ); } } } for( i = 0; i < points.length; i++ ){ for( j = 0; j < points[i].length; j++ ){ var point = points[i][j]; point.setVanishingPoint( stage.stageWidth / 2, stage.stageHeight / 2 ); point.setCenter( 0, 0, 50); } } stage.setPoint( points ); //set Triangle for( i = 0, n = points.length - 1; i < n; i++ ){ var pArray = points[i]; var pArray2 = points[i+1]; if( pArray.length == 1 ){ for( j = 0, m = pArray2.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[0], pArray2[j+1], pArray2[j], color ) ); } stage.setTriangles( new Triangle( pArray[0], pArray2[0], pArray2[pArray2.length-1], color ) ); } else if( pArray2.length == 1 ){ for( j = 0, m = pArray.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[j], pArray[j+1], pArray2[0], color ) ); } stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray[0], pArray2[0], color ) ); } else { for( j = 0, m = pArray.length-1; j < m; j++ ){ stage.setTriangles( new Triangle( pArray[j], pArray2[j+1], pArray2[j], color ) ); stage.setTriangles( new Triangle( pArray[j], pArray[j+1], pArray2[j+1], color ) ); } stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray2[0], pArray2[pArray.length-1], color ) ); stage.setTriangles( new Triangle( pArray[pArray.length-1], pArray[0], pArray2[0], color ) ); } } // set lights var triangles = stage.triangles; var light = new Light(); for( i = 0; i < triangles.length; i++ ){ triangles[i].light = light; } stage.start(); }})(); <canvas id='canvas' width="445" height="445"></canvas> body { background-color: #ffffff; font: 30px sans-serif; } use an iframe compat browser, deer Play on jsdo.it games Share Embed QR Tag Download Complete! Description どんなゲームですか? Control Device スマートフォンコントローラー jsdo.it WebSocket Controller» マウス キーボード タッチデバイス Fullscreen 有効 無効 jsdo.it games から削除する Submit Tweet style Design view Code view code <script type="text/javascript" src="http://jsdo.it/blogparts/y279/js?view=design"></script><p class="ttlBpJsdoit" style="width: 465px; margin: 0; text-align: right; font-size: 11px;"><a href="http://jsdo.it/_wonder/y279" title="3D Sphere">3D Sphere - jsdo.it - share JavaScript, HTML5 and CSS</a></p> 3D Tweet twitter Tags 3D canvas html5_elements&api polygon sphere Favorite by gaziya siouxcitizen.. shamotron norahiko yoshimax h6k Joost.Galjar.. sw_lucchini kabakiyo osamX hfeeqi rettuce phi narutohyper sv_junic clockmaker fingaholic y3i12 nehahelo canvastag kumaco: 3D gyunyu_whey: 3D alphabet_h: 3Dcanvas tetsuwo: 3dpolygonsphere Forked sort new page view favorite forked forked: 3D Sphere The_tall_man.. 00 12views 348/2/1 3D forked: 3D Sphere polmoneys 00 27views 348/2/1 art&design forked: 3D Sphere mkPg 00 20views 348/2/1 3D forked: 3D Sphere bbzn 00 23views 348/2/1 3D 1 2 3 4 5NEXT>>