UNPKG

matter-dom-plugin

Version:

A plugin to apply matter.js's physics to DOM elements

183 lines (153 loc) 6.54 kB
var RenderDom = {}; module.exports = function(Matter){ var Common = Matter.Common; var Composite = Matter.Composite; var Events = Matter.Events; var Render = Matter.Render; var _requestAnimationFrame, _cancelAnimationFrame; if (typeof window !== 'undefined'){ _requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(function(){callback(Common.now())}, 1000 / 60);}; _cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; } RenderDom.create = function(options){ var defaults = { engine: null, element: window, controller: RenderDom, frameRequestId: null, options: { } } /* try{ if(!options){ throw (new Error('No engine was specified. Create an options object and specify the engine with the engine property.')); } if(!options.engine){ throw (new Error('No engine was specified. Create an options object and specify the engine with the engine property.')); } }catch(e){ console.log(`${e.name}: ${e.message}`); return; }*/ var engine = options.engine; var render = Common.extend(defaults, options); render.mapping = {}; render.mapping.ratioMultiplier = 1/6; // VIEW is base ratio. Mapping to World. render.mapping.VIEW = { width: window.innerWidth, height: window.innerHeight }; render.mapping.VIEW.center = { x: render.mapping.VIEW.width/2, y: render.mapping.VIEW.height/2 }; render.mapping.WORLD = { width: render.mapping.VIEW.width * render.mapping.ratioMultiplier, height: render.mapping.VIEW.height * render.mapping.ratioMultiplier, }; render.mapping.WORLD.center = { x: render.mapping.WORLD.width/2, y: render.mapping.WORLD.height/2 }; render.mapping.viewToWorld = function(value){ if( typeof value === 'object' && value !== null ){ return { x: render.mapping.ratioMultiplier * value.x, y: render.mapping.ratioMultiplier * value.y }; }else{ return render.mapping.ratioMultiplier * value; } }; render.mapping.worldToView = function(value){ if( typeof value === 'object' && value !== null ){ return { x: value.x/render.mapping.ratioMultiplier, y: value.y/render.mapping.ratioMultiplier }; }else{ return value/render.mapping.ratioMultiplier; } }; var debugElement = document.querySelector('#debug'); debugElement.style.position = "absolute"; var debugRender = Render.create({ element: document.querySelector('#debug'), engine: engine, options: { width: render.mapping.WORLD.width, height: render.mapping.WORLD.height, background: '#fafafa', wireframeBackground: '#222', hasBounds: false, enabled: true, wireframes: true, showSleeping: true, showDebug: false, showBroadphase: false, showBounds: false, showVelocity: false, showCollisions: false, showAxes: false, showPositions: false, showAngleIndicator: false, showIds: false, showShadows: false } }); Render.run(debugRender); render.DebugRender = debugRender; return render; } RenderDom.run = function(render){ (function loop(time){ render.frameRequestId = _requestAnimationFrame(loop); RenderDom.world(render); })(); } RenderDom.stop = function(render){ _cancelAnimationFrame(render.frameRequestId); } RenderDom.world = function(render){ var engine = render.engine, world = engine.world, allBodies = Composite.allBodies(world), allConstraints = Composite.allConstraints(world), domBodies = document.querySelectorAll('[matter]'); var event = { timestamp: engine.timing.timestamp }; Events.trigger(render, 'beforeRender', event); // TODO bounds if specified RenderDom.bodies(render, domBodies); } /** * Map Dom view elements position to matter world bodys position */ RenderDom.bodies = function(render, bodies, context){ var c = context, engine = render.engine, world = engine.world, options = render.options, matterBodies = Composite.allBodies(world), domBody; for(var i=0; i<matterBodies.length; i++){ var matterBody = matterBodies[i]; for(var k=(matterBody.parts.length > 1) ? 1 : 0; k<matterBody.parts.length; k++){ var matterPart = matterBody.parts[k]; var domPart = matterPart.Dom.element; var bodyWorldPoint = render.mapping.worldToView({x: matterPart.position.x, y: matterPart.position.y}); var bodyViewOffset = {x: domPart.offsetWidth/2, y: domPart.offsetHeight/2}; domPart.style.position = "absolute"; domPart.style.transform = `translate(${bodyWorldPoint.x-bodyViewOffset.x}px, ${bodyWorldPoint.y-bodyViewOffset.y}px)`; domPart.style.transform += `rotate(${matterBody.angle}rad)`; } } } return RenderDom; };