Suddenly turn to the raffle software written by the company earlier (for the company’s annual meeting). I feel quite emotional, TM total 30+ people, about 15, the code is still written by me, but I can not draw me. (It really is, moral, mental)

A few words of emotion:

1, front random what, is really pseudo random!! (Behind myself, when testing randomness)

Please call me suture strange

A, effects,

Demo address (free Tencent cloud server, invalid on 2022/2/26)

The renderings are as follows:

Two, the basic effect

1. Periodic Table of Elements

The photo wall? Lottery? Just before I wrote it, I happened to be blogging and saw threejs version of the Periodic Table written by another great god. It had a similar effect. (AT that time I forgot the link, online casually find the code, thanks to the big god before)

We have the two most important pieces.

Then change the element and tip to the photo and name of the sweepstakes and render with CSS3DObject.

// table for ( var i = 0; i < table.length; I += 2) {var element = document.createElement('div'); element.className = 'element'; Element. The style. The backgroundColor = 'rgba (0127127,' + (Math) random () * 0.5 + 0.25) + ') '. Var number = document.createElement('div'); number.className = 'number'; number.textContent = (i/2) + 1; element.appendChild( number ); Var symbolBox = document.createElement('div'); var symbol = document.createElement( 'img' ); symbolBox.className = 'symbolBox'; symbol.className = 'symbol'; symbol.src = table[i]; symbolBox.appendChild(symbol); element.appendChild( symbolBox ); Var details = document.createElement('div'); details.className = 'details'; details.innerHTML = table[ i + 1 ]; element.appendChild( details ); Var object = new THREE.CSS3DObject(Element); object.position.x = Math.random() * 3400 - 1700; object.position.y = Math.random() * 3400 - 1700; object.position.z = Math.random() * 3400 - 1700; object.name=table[ i + 1 ]; scene.add( object ); objects.push( object ); Var object = new three.object3d (); var iy = Math.floor((i/2)/9); var ix = (i/2)%9; object.position.x = (ix * 140 ) -540; object.position.y = - ( iy * 180 ) + 480; targets.table.push( object ); }Copy the code

2. Starry sky base map and star animation

Light is too primitive for the periodic table. Definitely a star or something in the background, preferably a galaxy!

Hd star wallpaper, too big, if it is a bit of motion GIF, that volume is even bigger. And low pixels, it doesn’t work at all. (Suitable for 1920 screen)

So I used a low pixel image + Canvas star GIF to complete the background!

Star Canvas animation. (also found on the Internet, forget the link) (thanks to the previous god + 1)

var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width = window.innerWidth, h = canvas.height = window.innerHeight, hue = 217, stars = [], count = 0, maxStars = 1300; Var canvas2 = document.createElement('canvas'), ctx2 = canvas2.getContext('2d'); canvas2.width = 100; canvas2.height = 100; var half = canvas2.width / 2, gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half); Gradient2. AddColorStop (0.025, # 'CCC'); Gradient2. AddColorStop (0.1, 'an HSL (' + +' hue, 61%, 33%) '); Gradient2. AddColorStop (0.25, 'an HSL (' + +' hue, 64%, 6%) '); gradient2.addColorStop(1, 'transparent'); ctx2.fillStyle = gradient2; ctx2.beginPath(); ctx2.arc(half, half, half, 0, Math.PI * 2); ctx2.fill(); // End cache function random(min, max) { if (arguments.length < 2) { max = min; min = 0; } if (min > max) { var hold = max; max = min; min = hold; } return Math.floor(Math.random() * (max - min + 1)) + min; } function maxOrbit(x, y) { var max = Math.max(x, y), diameter = Math.round(Math.sqrt(max * max + max * max)); return diameter / 2; } var Star = function() {this.orbitradius = random(maxOrbit(w, h)); this.radius = random(60, this.orbitRadius) / 8; OrbitX = w / 2; this.orbitY = h / 2; this.timePassed = random(0, maxStars); this.speed = random(this.orbitRadius) / 50000; This. alpha = random(2, 10) / 10; count++; stars[count] = this; } Star.prototype.draw = function() { var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX, y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY, twinkle = random(10); If (twinkle == 1 && this. Alpha > 0) {this. Alpha -= 0.05; } else if (twinkle == 2 &&this. Alpha < 1) {this.alpha += 0.05; } ctx.globalAlpha = this.alpha; ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius); this.timePassed += this.speed; } for (var i = 0; i < maxStars; i++) { new Star(); } function animation() { ctx.globalCompositeOperation = 'source-over'; CTX. GlobalAlpha = 0.5; / / tail CTX. FillStyle = 'hsla (' + +' hue, 64%, 6%, 2) '; ctx.fillRect(0, 0, w, h) ctx.globalCompositeOperation = 'lighter'; for (var i = 1, l = stars.length; i < l; i++) { stars[i].draw(); }; window.requestAnimationFrame(animation); } animation();Copy the code

3. Photos of the lucky draw

The raffle photo has to be in the middle of the photo ball. (Also in 3D)

In the same way, render using CSS3DObject

Var elements = document.createElement('div'); elements.className = 'changeImgBoxs'; // element.style.backgroundImage = "url(./img/pic.png)"; Elements. The style. The backgroundColor = 'rgba (0127127,' + (Math) random () * 0.5 + 0.25) + ') '. var symbolBox = document.createElement( 'div' ); var symbol = document.createElement( 'img' ); symbol.setAttribute("id", "changeImg"); symbolBox.className = 'symbolBox2'; symbol.className = 'symbol2'; symbol.src = table[0]; symbolBox.appendChild(symbol); elements.appendChild( symbolBox ); var details = document.createElement( 'div' ); details.setAttribute("id", "detailss"); details.className = 'details'; details.innerHTML = table[1]; elements.appendChild( details ); objectsss = new THREE.CSS3DObject( elements ); objectsss.position.x = 0; objectsss.position.y = 20000; objectsss.position.z = 0; scene.add( objectsss );Copy the code

Second, the animation

All the basics are in place except animation.

1. Tween animation of photo wall, photo ball and photo scattered state

Click on the lucky draw: Photo Wall –> Photo Ball

Click stop: Photo ball –> Photos are scattered (it feels like the photo ball exploded)

In Threejs, tween animation is usually used with tween.js

First save the coordinate points of the three states of photo wall, ball and scattered, and then switch the lottery state, at the same time switch, through tween to switch the position of the photo, so as to achieve animation.

Object.position. x = math.random () * 3400-1700; object.position.y = Math.random() * 3400 - 1700; object.position.z = Math.random() * 3400 - 1700; object.name=table[ i + 1 ]; scene.add( object ); objects.push( object ); Var object = new three.object3d (); var iy = Math.floor((i/2)/9); var ix = (i/2)%9; object.position.x = (ix * 140 ) -540; object.position.y = - ( iy * 180 ) + 480; targets.table.push( object ); Var vector = new three.vector3 (); for ( var i = 0, l = objects.length; i < l; i ++ ) { var phi = Math.acos( -1 + ( 2 * i ) / l ); var theta = Math.sqrt( l * Math.PI ) * phi; var object = new THREE.Object3D(); object.position.x = 750 * Math.cos( theta ) * Math.sin( phi ); object.position.y = 750 * Math.sin( theta ) * Math.sin( phi ); object.position.z = 750 * Math.cos( phi ); vector.copy( object.position ).multiplyScalar( 2 ); object.lookAt( vector ); targets.sphere.push( object ); } var vector = new three.vector3 (); for ( var i = 0, l = objects.length; i < l; i ++ ) { var phi = Math.acos( -1 + ( 2 * i ) / l ); var theta = Math.sqrt( l * Math.PI ) * phi; var object = new THREE.Object3D(); var py = Math.random() * 3400 - 1700; If (py<400&&py>-400){// if(py<0){py-=400; }else{ py+=400; } } object.position.x = Math.random() * 3400 - 1700; object.position.y = py; object.position.z = Math.random() * 3400 - 1700; object.lookAt( vector ); targets.chaos.push( object ); }Copy the code

Tweenjs patch animation

Function transform(targets, duration,type) {var scale = 1; if(type==undefined){ type=0; } TWEEN.removeAll(); for ( var i = 0; i < objects.length; i ++ ) { var object = objects[ i ]; var target = targets[ i ]; new TWEEN.Tween( object.position ) .to( { x: target.position.x, y: target.position.y, z: target.position.z }, Math.random() * duration + duration ) .easing( TWEEN.Easing.Exponential.InOut ) .start(); new TWEEN.Tween( object.rotation ) .to( { x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration ) .easing( TWEEN.Easing.Exponential.InOut ) .start(); } new TWEEN.Tween( this ) .to( {}, duration * 2 ) .onUpdate( render ) .start(); }Copy the code

2. Animation during lottery

At this time, the animation is mainly two: photo switching, photo ball rotation

Photo toggle, middle image SRC random toggle good

Photo ball rotation? Why? Wouldn’t it be easier to turn the camera?

So use: TrackballControls.js track controller. Just turn the camera

var numsss =0,srcss='',txtsss=''; Function movings(){// Camera rotation ang += math.pi /50; camera.position.x = Math.cos(ang)*2000; camera.position.z = Math.sin(ang)*2000; camera.position.y = 0; // Camera orientation reset camera.up.x = 0; camera.up.y = 1; camera.up.z = 0; Rotation. Y =-ang+ math.pi /2; Numsss = math.floor (math.random ()*tableLens); if(numsss==tableLens){ numsss = tableLens-1; } srcss = table[numsss*2]; txtsss = table[numsss*2+1]; changeImg.src = srcss; detailss.innerHTML = txtsss; }Copy the code

3. Enlarge the winning picture after the drawing

Draw end, stop rotating, the winning picture enlargement

Function objDeal(obj,nums){var option = {x: obj.scale.x, y: obj.scale.y, z: obj.scale.z,}; var tween = new TWEEN.Tween(option).to({ x:nums, y:nums, z:nums, },300).delay(100).onUpdate(function() { obj.scale.x = this.x; obj.scale.y = this.y; obj.scale.z = this.z; isMoving = true; }).onComplete(function(){ isMoving = false; }).start(); }Copy the code

Three, perfect the details, add music

Lucky draw, the effect is not enough, also need some music. (The music was provided by my sister.)

Now add 2 music: click on the draw after the exciting music “Pig Advance”. Jackpot music, a ringtone of Booing Booing.

<! --> <audio id="music" SRC ="./music/04 --> <audio ><! <audio id="music2" SRC ="./music/9629.mp3"></audio> // start:function(){if(vm.spic! "> < span style =" max-width: 100%; clear: both; min-height: 1em; ); return; } moving = true; objectsss.position.y = 0; transform( targets.sphere, 1000 ); objDeal(objectsss,1); music.play(); // start music this.ckprice (); Watches :function(){music-.pause (); // Turn off music if(! moving){ return; } music2.play(); // Play movin = false; this.choosePerson(); transform( targets.chaos, 250 ,1); ObjDeal (objectsss, 1.8); },Copy the code

Fourth, concluding remarks

The code was written a few years ago, it’s pretty rubbish, no performance consideration, no optimization. Just at that time to do the train of thought is relatively clear. Give you a look, to provide some ideas of relevant business.

Happy New Year to you all.

Code, you can pick directly on demo.

Demo address (free Tencent cloud server, invalid on 2022/2/26)