Canvas Oil Pump Jack
Forked from Marko Švaljek's Pen Canvas Oil Pump Jack.
A Pen by Michael Abraham Vieth on CodePen.
Canvas Oil Pump Jack
Forked from Marko Švaljek's Pen Canvas Oil Pump Jack.
A Pen by Michael Abraham Vieth on CodePen.
| <canvas id="mainCanvas" width="600" height="300"></canvas> |
| // https://twitter.com/msvaljek | |
| // http://msvaljek.blogspot.com/2013/05/canvas-circular-motions-and-networks.html | |
| window.requestAnimFrame = (function(){ | |
| return window.requestAnimationFrame || | |
| window.webkitRequestAnimationFrame || | |
| window.mozRequestAnimationFrame || | |
| function( callback ) { | |
| window.setTimeout(callback, 1000 / 60); | |
| }; | |
| })(); | |
| var canvas = document.getElementById('mainCanvas'), | |
| ctx = canvas.getContext('2d'), | |
| groundHeight = 290, | |
| groundPartWidth = 5, | |
| engineBodyHeight = 70, | |
| engineBodyWidth = 30, | |
| engineX = 100, | |
| engineY = groundHeight - Math.floor(engineBodyHeight * 9 / 10), | |
| engineCrankL = 40, | |
| engineCrankWidth = 5, | |
| beamWidth = 15, | |
| engineCrankWeightRadius = 15, | |
| samsonPostWidth = 30, | |
| samsonPostX = 250, | |
| samsonPostY = groundHeight - 150, | |
| rodLength = 80, | |
| beamHalfLength = 155, | |
| headWidth = 20, | |
| headNoseHeight = 70, | |
| polishedRodSize = 20, | |
| polishedRodOffset = 100, | |
| angle = 0, | |
| dAngle = 0.025, // rotational speed | |
| oilpump = { | |
| draw : function () { | |
| ctx.save(); | |
| // ground | |
| ctx.strokeStyle = '#9EA18C'; | |
| ctx.fillStyle = '#9EA18C'; | |
| ctx.strokeStyle = '#9EA18C'; | |
| ctx.fillStyle = '#9EA18C'; | |
| var i = 0; | |
| ctx.beginPath(); | |
| ctx.moveTo(0, canvas.height); | |
| while (i < canvas.width) { | |
| ctx.lineTo(i + groundPartWidth, groundHeight); | |
| ctx.moveTo(i += groundPartWidth, canvas.height); | |
| } | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(0, groundHeight); | |
| ctx.lineTo(canvas.width, groundHeight); | |
| ctx.stroke(); | |
| // engine body | |
| ctx.strokeStyle = '#FF3333'; | |
| ctx.fillStyle = '#FF3333'; | |
| ctx.fillRect(engineX - engineBodyWidth / 2, groundHeight - engineBodyHeight, engineBodyWidth, engineBodyHeight); | |
| // engine crank | |
| ctx.strokeStyle = '#808080'; | |
| ctx.fillStyle = '#808080'; | |
| angle += dAngle; | |
| ctx.lineWidth = engineCrankWidth; | |
| ctx.beginPath(); | |
| ctx.arc(engineX, engineY, ctx.lineWidth, 0, 2 * Math.PI); // crank joint | |
| ctx.fill(); | |
| ctx.beginPath(); | |
| ctx.moveTo(engineX, engineY); | |
| ctx.lineTo(engineX + Math.cos(angle) * (engineCrankL + ctx.lineWidth), | |
| engineY + Math.sin(angle) * (engineCrankL+ ctx.lineWidth)); | |
| ctx.stroke(); | |
| // crank weight | |
| ctx.save(); | |
| ctx.translate(engineX + Math.cos(angle) * engineCrankL, engineY + Math.sin(angle) * engineCrankL); | |
| ctx.rotate(angle); | |
| ctx.beginPath(); | |
| ctx.arc(0, 0, engineCrankWeightRadius, -Math.PI / 2, Math.PI / 2); | |
| ctx.fill(); | |
| ctx.restore(); | |
| // pitman arm | |
| ctx.strokeStyle = 'black'; | |
| ctx.fillStyle = 'black'; | |
| var crankJoinX = engineX + Math.cos(angle) * engineCrankL * 0.7; | |
| var crankJoinY = engineY + Math.sin(angle) * engineCrankL * 0.7; | |
| ctx.beginPath(); | |
| ctx.moveTo(crankJoinX, crankJoinY); | |
| var pitmanY = crankJoinY - Math.sqrt(Math.pow(rodLength, 2) - Math.pow(crankJoinX - engineX, 2)); | |
| ctx.lineTo(engineX, pitmanY); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.arc(crankJoinX, crankJoinY, ctx.lineWidth, 0, 2 * Math.PI); // arm joint | |
| ctx.fill(); | |
| // samson post | |
| ctx.strokeStyle = '#808080'; | |
| ctx.fillStyle = '#808080'; | |
| ctx.beginPath(); | |
| ctx.moveTo(samsonPostX, samsonPostY); | |
| ctx.lineTo(samsonPostX - samsonPostWidth / 2, groundHeight); | |
| ctx.lineTo(samsonPostX + samsonPostWidth / 2, groundHeight); | |
| ctx.lineTo(samsonPostX, samsonPostY); | |
| ctx.fill(); | |
| // walking beam | |
| ctx.strokeStyle = '#808080'; | |
| ctx.fillStyle = '#808080'; | |
| ctx.lineWidth = beamWidth; | |
| ctx.beginPath(); | |
| ctx.moveTo(samsonPostX, samsonPostY); | |
| var beamDX = Math.sqrt(Math.pow(beamHalfLength, 2) - Math.pow(samsonPostY - pitmanY, 2)); | |
| ctx.lineTo(samsonPostX - beamDX, pitmanY); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(samsonPostX, samsonPostY); | |
| var headX = samsonPostX + beamDX; | |
| var headY = 2 * samsonPostY - pitmanY; | |
| ctx.lineTo(headX, headY); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.arc(samsonPostX - beamDX, pitmanY, ctx.lineWidth / 2, 0, 2 * Math.PI); // ending joint | |
| ctx.fill(); | |
| // bridle | |
| ctx.lineWidth = engineCrankWidth; | |
| ctx.strokeStyle = 'black'; | |
| ctx.fillStyle = 'black'; | |
| ctx.beginPath(); | |
| ctx.moveTo(samsonPostX + beamHalfLength + headWidth - ctx.lineWidth, headY); | |
| ctx.lineTo(samsonPostX + beamHalfLength + headWidth - ctx.lineWidth, groundHeight); | |
| ctx.stroke(); | |
| // polished rod | |
| ctx.fillRect(samsonPostX + beamHalfLength + headWidth - ctx.lineWidth - polishedRodSize / 2, | |
| headY + polishedRodOffset, polishedRodSize, polishedRodSize); | |
| // head | |
| ctx.strokeStyle = '#FF3333'; | |
| ctx.fillStyle = '#FF3333'; | |
| ctx.save(); | |
| ctx.translate(headX, headY); | |
| ctx.rotate(Math.asin((samsonPostY - pitmanY) / beamDX)); | |
| ctx.beginPath(); | |
| ctx.fillRect(0, ctx.lineWidth / 2 - 2 * headWidth, headWidth, 2 * headWidth); | |
| ctx.stroke(); | |
| ctx.restore(); | |
| ctx.beginPath(); | |
| ctx.arc(samsonPostX, samsonPostY, beamHalfLength + headWidth, | |
| Math.asin((samsonPostY - pitmanY) / beamHalfLength), | |
| Math.asin((samsonPostY - pitmanY + headNoseHeight) / beamHalfLength)); | |
| ctx.lineTo(headX, headY); | |
| ctx.fill(); | |
| // restore | |
| ctx.restore(); | |
| } | |
| }; | |
| (function animloop(){ | |
| requestAnimFrame(animloop); | |
| ctx.clearRect(0, 0, canvas.width, canvas.height); | |
| oilpump.draw(); | |
| })(); |
| * { | |
| padding: 10px; | |
| } | |
| html, body { | |
| width:100%; | |
| height:100%; | |
| background: white; | |
| } |