diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..9127b794 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +## next +- fully typed +- added `lineWidth` option + +## 1.0.0 +- ported to typescript +- added distributable library build in dist folder +- some minor fixes diff --git a/src/demo/demo.js b/src/demo/demo.js index 2258ad8d..1976599b 100644 --- a/src/demo/demo.js +++ b/src/demo/demo.js @@ -1,5 +1,3 @@ - - let gcodePreview; const slider = document.getElementById('layers'); @@ -7,11 +5,13 @@ const scaleSlider = document.getElementById('scale'); const rotationSlider = document.getElementById('rotation'); const toggleAnimation = document.getElementById('toggle-animation'); const toggleZoneColors = document.getElementById('zone-colors'); +const lineWidth = document.getElementById('line-width'); function initDemo() { const preview = new GCodePreview.Preview({ targetId : 'renderer', scale: 7, + lineWidth: 0.6 }); info(preview.canvas); @@ -31,6 +31,11 @@ function initDemo() { preview.render(); }) + lineWidth.addEventListener('input', function(evt) { + preview.lineWidth = +lineWidth.value; + preview.render(); + }) + window.addEventListener('resize', function() { preview.resize(); preview.render(); diff --git a/src/demo/index.html b/src/demo/index.html index e6d216d0..4769bc9f 100644 --- a/src/demo/index.html +++ b/src/demo/index.html @@ -8,6 +8,7 @@

GCode Previewer

+
diff --git a/src/dist/gcode-parser.d.ts b/src/dist/gcode-parser.d.ts index ffdc5132..3b92b0f7 100644 --- a/src/dist/gcode-parser.d.ts +++ b/src/dist/gcode-parser.d.ts @@ -7,21 +7,20 @@ export declare class MoveCommand extends GCodeCommand { params: MoveCommandParams; constructor(gcode: string, params: MoveCommandParams, comment?: string); } +declare type MoveCommandParamName = "x" | "y" | "z" | "e"; declare type MoveCommandParams = { - x?: number; - y?: number; - z?: number; - e?: number; + [key in MoveCommandParamName]?: number; }; -export interface Layer { +export declare class Layer { layer: number; commands: GCodeCommand[]; + constructor(layer: number, commands: GCodeCommand[]); } export declare class Parser { parseCommand(line: string, keepComments?: boolean): GCodeCommand | null; parseMove(params: string[]): MoveCommandParams; - groupIntoLayers(commands: GCodeCommand[], header: any): Layer[]; - parseGcode(input: any): { + groupIntoLayers(commands: GCodeCommand[]): Layer[]; + parseGcode(input: string): { header: { slicer: string; }; diff --git a/src/dist/gcode-preview.d.ts b/src/dist/gcode-preview.d.ts index c1c36c91..399ebe53 100644 --- a/src/dist/gcode-preview.d.ts +++ b/src/dist/gcode-preview.d.ts @@ -1,12 +1,23 @@ import Colors from "./gcode-colors"; import { Parser, Layer } from "./gcode-parser"; export { Colors }; -export declare class Preview { +declare type PreviewOptions = Partial<{ + limit: number; + scale: number; + lineWidth: number; + rotation: number; + rotationAnimation: boolean; + zoneColors: boolean; + canvas: HTMLCanvasElement | string; + targetId: string; +}>; +export declare class Preview implements PreviewOptions { limit: number; rotation: number; - rotationAnimation: Boolean; + lineWidth: number; + rotationAnimation: boolean; scale: number; - zoneColors: Boolean; + zoneColors: boolean; canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; targetId: string; @@ -23,14 +34,13 @@ export declare class Preview { x: number; y: number; }; - constructor(opts: any); + constructor(opts: PreviewOptions); clear(): void; resize(): void; - getZoneColor(zone: any, layerIndex: any): any; - renderWithColor(l: Layer, layerIndex: number, color?: any): void; - drawLayer(index: any, limit: any): void; + renderWithColor(l: Layer, layerIndex: number, color?: string): void; + drawLayer(index: number, limit: number): void; render(): void; - processGCode(gcode: any): void; + processGCode(gcode: string): void; animationLoop(): void; startAnimation(): void; stopAnimation(): void; @@ -40,7 +50,7 @@ export declare class Preview { minY: number; maxY: number; }; - getCenter(layer: any): { + getCenter(layer: Layer): { x: number; y: number; }; @@ -52,8 +62,8 @@ export declare class Preview { sizeX: number; sizeY: number; }; - drawBounds(layer: any, color: any): void; - autoscale(): any; + drawBounds(layer: Layer, color: string): void; + autoscale(): number; projectIso(point: { x: number; y: number; diff --git a/src/dist/gcode-preview.es.js b/src/dist/gcode-preview.es.js index bc904414..51547675 100644 --- a/src/dist/gcode-preview.es.js +++ b/src/dist/gcode-preview.es.js @@ -1 +1 @@ -var t={Cura_SteamEngine:{skirt:"lime","wall-inner":"purple","wall-outer":"blue",skin:"red",fill:"orange",support:"rgba(255,255,255,0.5)"},Simplify3D:{skirt:"lime","inner perimeter":"purple","outer perimeter":"blue",skin:"solid layer",fill:"infill",support:"rgba(255,255,255,0.5)"}};class e{constructor(t,e){this.gcode=t,this.comment=e}}class s extends e{constructor(t,e,s){super(t,s),this.params=e}}class i{parseCommand(t,e=!0){const i=t.trim().split(";"),a=i[0],r=e&&i[1]||null,n=a.split(/ +/g),o=n[0].toLowerCase();switch(o){case"g0":case"g1":const t=this.parseMove(n.slice(1));return new s(o,t,r);default:return null}}parseMove(t){return t.reduce((t,e)=>(t[e.slice(0,1).toLowerCase()]=+e.slice(1),t),{})}groupIntoLayers(t,e){const i=[];let a,r=0;for(const e of t.filter(t=>t instanceof s)){const t=e.params;t.z&&t.z>r&&(0!=r||t.z<2)?(r=t.z,a={layer:i.length,commands:[e]},i.push(a)):a&&a.commands.push(e)}return i}parseGcode(t){const e=t.split("\n").filter(t=>t.length>0).map(t=>this.parseCommand(t)).filter(t=>null!==t),s={slicer:"MySlicer"},i=this.groupIntoLayers(e,s);return{header:s,layers:i,limit:i.length-1}}parseHeader(t){return{slicer:t.filter(t=>null!==t.comment).map(t=>t.comment).filter(t=>/(G|g)enerated/.test(t)).map(t=>t.includes("Slic3r")?"Slic3r":t.includes("Simplify3D")?"Simplify3D":t.includes("Cura_SteamEngine")?"Cura_SteamEngine":void 0)[0]}}}class a{constructor(t){if(this.parser=new i,this.limit=t.limit,this.scale=t.scale,this.rotation=void 0===t.rotation?0:t.rotation,this.rotationAnimation=t.rotationAnimation,this.zoneColors=t.zoneColors,t.canvas instanceof HTMLCanvasElement)this.canvas=t.canvas,this.ctx=this.canvas.getContext("2d");else{this.targetId=t.targetId;const e=document.getElementById(this.targetId);if(!e)throw new Error("Unable to find element "+this.targetId);this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),e.appendChild(this.canvas),this.resize()}}clear(){this.ctx.clearRect(-this.canvas.width/2,-this.canvas.height/2,this.canvas.width,this.canvas.height)}resize(){this.canvas.width=this.canvas.parentNode.offsetWidth,this.canvas.height=this.canvas.offsetHeight}getZoneColor(e,s){const i=Math.round(s/this.layers.length*80);return this.zoneColors?t[this.header.slicer][e]:"hsl(0, 0%, "+i+"%)"}renderWithColor(t,e,s){if(s)this.ctx.strokeStyle=s;else{const t=Math.round(e/this.layers.length*80);this.ctx.strokeStyle="hsl(0, 0%, "+t+"%)"}this.ctx.beginPath();for(const e of t.commands)if("g0"==e.gcode){const t=e;this.ctx.moveTo(t.params.x,t.params.y)}else if("g1"==e.gcode){const t=e;t.params.e>0?this.ctx.lineTo(t.params.x,t.params.y):this.ctx.moveTo(t.params.x,t.params.y)}this.ctx.stroke()}drawLayer(t,e){if(t>e)return;const s=this.layers[t],i=this.projectIso({x:0,y:0},t);this.ctx.save(),this.ctx.scale(this.scale,this.scale),this.ctx.translate(i.x,i.y),this.ctx.rotate(this.rotation*Math.PI/180),this.ctx.translate(-this.center.x,-this.center.y),this.renderWithColor(s,t),this.ctx.restore()}render(){this.canvas.width=this.canvas.width,this.ctx.lineWidth=.6,this.ctx.scale(1,-1),this.ctx.translate(this.canvas.width/2,-this.canvas.height/2),this.center=this.getAdjustedCenter();for(let t=0;ti&&(i=t.params.x),t.params.yr&&(r=t.params.y))}return{minX:s,maxX:i,minY:a,maxY:r}}getCenter(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{x:s.minX+(s.maxX-s.minX)/2,y:s.minY+(s.maxY-s.minY)/2}}getAdjustedCenter(){const t=this.getCenter(this.layers[0]);return this.maxProjectionOffset=this.projectIso({x:0,y:0},this.layers.length-1),t.x+=this.maxProjectionOffset.x/2,t.y+=this.maxProjectionOffset.y/2,t}getSize(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{sizeX:s.maxX-s.minX,sizeY:s.maxY-s.minY}}drawBounds(t,e){this.ctx.strokeStyle=e;const{minX:s,maxX:i,minY:a,maxY:r}=this.getOuterBounds(t);console.log(s,a,i-s,r-a),this.ctx.strokeRect(s,a,i-s,r-a)}autoscale(){const{sizeX:t,sizeY:e}=this.getSize(),{width:s,height:i}=this.canvas;var a;return a=t/e>s/i?s/t:i/e,a*=.2}projectIso(t,e){return{x:t.x,y:t.y+.1*e}}}export{t as Colors,a as Preview}; +var t={Cura_SteamEngine:{skirt:"lime","wall-inner":"purple","wall-outer":"blue",skin:"red",fill:"orange",support:"rgba(255,255,255,0.5)"},Simplify3D:{skirt:"lime","inner perimeter":"purple","outer perimeter":"blue",skin:"solid layer",fill:"infill",support:"rgba(255,255,255,0.5)"}};class e{constructor(t,e){this.gcode=t,this.comment=e}}class s extends e{constructor(t,e,s){super(t,s),this.params=e}}class i{constructor(t,e){this.layer=t,this.commands=e}}class a{parseCommand(t,e=!0){const i=t.trim().split(";"),a=i[0],r=e&&i[1]||null,n=a.split(/ +/g),o=n[0].toLowerCase();switch(o){case"g0":case"g1":const t=this.parseMove(n.slice(1));return new s(o,t,r);default:return null}}parseMove(t){return t.reduce((t,e)=>{const s=e.slice(0,1).toLowerCase();return"x"!=s&&"y"!=s&&"z"!=s&&"e"!=s||(t[s]=+e.slice(1)),t},{})}groupIntoLayers(t){const e=[];let a,r=0;for(const n of t.filter(t=>t instanceof s)){const t=n.params;t.z&&t.z>r&&(0!=r||t.z<2)?(r=t.z,a=new i(e.length,[n]),e.push(a)):a&&a.commands.push(n)}return e}parseGcode(t){const e=t.split("\n").filter(t=>t.length>0).map(t=>this.parseCommand(t)).filter(t=>null!==t),s=this.groupIntoLayers(e);return{header:{slicer:"MySlicer"},layers:s,limit:s.length-1}}parseHeader(t){return{slicer:t.filter(t=>null!==t.comment).map(t=>t.comment).filter(t=>/(G|g)enerated/.test(t)).map(t=>t.includes("Slic3r")?"Slic3r":t.includes("Simplify3D")?"Simplify3D":t.includes("Cura_SteamEngine")?"Cura_SteamEngine":void 0)[0]}}}class r{constructor(t){if(this.parser=new a,this.limit=t.limit,this.scale=t.scale,this.lineWidth=t.lineWidth||.6,this.rotation=void 0===t.rotation?0:t.rotation,this.rotationAnimation=t.rotationAnimation,this.zoneColors=t.zoneColors,t.canvas instanceof HTMLCanvasElement)this.canvas=t.canvas,this.ctx=this.canvas.getContext("2d");else{this.targetId=t.targetId;const e=document.getElementById(this.targetId);if(!e)throw new Error("Unable to find element "+this.targetId);this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),e.appendChild(this.canvas),this.resize()}}clear(){this.ctx.clearRect(-this.canvas.width/2,-this.canvas.height/2,this.canvas.width,this.canvas.height)}resize(){this.canvas.width=this.canvas.parentNode.offsetWidth,this.canvas.height=this.canvas.offsetHeight}renderWithColor(t,e,s){if(s)this.ctx.strokeStyle=s;else{const t=Math.round(e/this.layers.length*80);this.ctx.strokeStyle="hsl(0, 0%, "+t+"%)"}this.ctx.beginPath();for(const e of t.commands)if("g0"==e.gcode){const t=e;this.ctx.moveTo(t.params.x,t.params.y)}else if("g1"==e.gcode){const t=e;t.params.e>0?this.ctx.lineTo(t.params.x,t.params.y):this.ctx.moveTo(t.params.x,t.params.y)}this.ctx.stroke()}drawLayer(t,e){if(t>e)return;const s=this.layers[t],i=this.projectIso({x:0,y:0},t);this.ctx.save(),this.ctx.scale(this.scale,this.scale),this.ctx.translate(i.x,i.y),this.ctx.rotate(this.rotation*Math.PI/180),this.ctx.translate(-this.center.x,-this.center.y),this.renderWithColor(s,t),this.ctx.restore()}render(){this.canvas.width=this.canvas.width,this.ctx.lineWidth=this.lineWidth,this.ctx.scale(1,-1),this.ctx.translate(this.canvas.width/2,-this.canvas.height/2),this.center=this.getAdjustedCenter();for(let t=0;ti&&(i=t.params.x),t.params.yr&&(r=t.params.y))}return{minX:s,maxX:i,minY:a,maxY:r}}getCenter(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{x:s.minX+(s.maxX-s.minX)/2,y:s.minY+(s.maxY-s.minY)/2}}getAdjustedCenter(){const t=this.getCenter(this.layers[0]);return this.maxProjectionOffset=this.projectIso({x:0,y:0},this.layers.length-1),t.x+=this.maxProjectionOffset.x/2,t.y+=this.maxProjectionOffset.y/2,t}getSize(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{sizeX:s.maxX-s.minX,sizeY:s.maxY-s.minY}}drawBounds(t,e){this.ctx.strokeStyle=e;const{minX:s,maxX:i,minY:a,maxY:r}=this.getOuterBounds(t);console.log(s,a,i-s,r-a),this.ctx.strokeRect(s,a,i-s,r-a)}autoscale(){const{sizeX:t,sizeY:e}=this.getSize(),{width:s,height:i}=this.canvas;var a;return a=t/e>s/i?s/t:i/e,a*=.2}projectIso(t,e){return{x:t.x,y:t.y+.1*e}}}export{t as Colors,r as Preview}; diff --git a/src/dist/gcode-preview.js b/src/dist/gcode-preview.js index 4f733575..ee136d6f 100644 --- a/src/dist/gcode-preview.js +++ b/src/dist/gcode-preview.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).GCodePreview={})}(this,function(t){"use strict";var e={Cura_SteamEngine:{skirt:"lime","wall-inner":"purple","wall-outer":"blue",skin:"red",fill:"orange",support:"rgba(255,255,255,0.5)"},Simplify3D:{skirt:"lime","inner perimeter":"purple","outer perimeter":"blue",skin:"solid layer",fill:"infill",support:"rgba(255,255,255,0.5)"}};class s{constructor(t,e){this.gcode=t,this.comment=e}}class i extends s{constructor(t,e,s){super(t,s),this.params=e}}class r{parseCommand(t,e=!0){const s=t.trim().split(";"),r=s[0],n=e&&s[1]||null,a=r.split(/ +/g),o=a[0].toLowerCase();switch(o){case"g0":case"g1":const t=this.parseMove(a.slice(1));return new i(o,t,n);default:return null}}parseMove(t){return t.reduce((t,e)=>(t[e.slice(0,1).toLowerCase()]=+e.slice(1),t),{})}groupIntoLayers(t,e){const s=[];let r,n=0;for(const e of t.filter(t=>t instanceof i)){const t=e.params;t.z&&t.z>n&&(0!=n||t.z<2)?(n=t.z,r={layer:s.length,commands:[e]},s.push(r)):r&&r.commands.push(e)}return s}parseGcode(t){const e=t.split("\n").filter(t=>t.length>0).map(t=>this.parseCommand(t)).filter(t=>null!==t),s={slicer:"MySlicer"},i=this.groupIntoLayers(e,s);return{header:s,layers:i,limit:i.length-1}}parseHeader(t){return{slicer:t.filter(t=>null!==t.comment).map(t=>t.comment).filter(t=>/(G|g)enerated/.test(t)).map(t=>t.includes("Slic3r")?"Slic3r":t.includes("Simplify3D")?"Simplify3D":t.includes("Cura_SteamEngine")?"Cura_SteamEngine":void 0)[0]}}}t.Colors=e,t.Preview=class{constructor(t){if(this.parser=new r,this.limit=t.limit,this.scale=t.scale,this.rotation=void 0===t.rotation?0:t.rotation,this.rotationAnimation=t.rotationAnimation,this.zoneColors=t.zoneColors,t.canvas instanceof HTMLCanvasElement)this.canvas=t.canvas,this.ctx=this.canvas.getContext("2d");else{this.targetId=t.targetId;const e=document.getElementById(this.targetId);if(!e)throw new Error("Unable to find element "+this.targetId);this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),e.appendChild(this.canvas),this.resize()}}clear(){this.ctx.clearRect(-this.canvas.width/2,-this.canvas.height/2,this.canvas.width,this.canvas.height)}resize(){this.canvas.width=this.canvas.parentNode.offsetWidth,this.canvas.height=this.canvas.offsetHeight}getZoneColor(t,s){const i=Math.round(s/this.layers.length*80);return this.zoneColors?e[this.header.slicer][t]:"hsl(0, 0%, "+i+"%)"}renderWithColor(t,e,s){if(s)this.ctx.strokeStyle=s;else{const t=Math.round(e/this.layers.length*80);this.ctx.strokeStyle="hsl(0, 0%, "+t+"%)"}this.ctx.beginPath();for(const e of t.commands)if("g0"==e.gcode){const t=e;this.ctx.moveTo(t.params.x,t.params.y)}else if("g1"==e.gcode){const t=e;t.params.e>0?this.ctx.lineTo(t.params.x,t.params.y):this.ctx.moveTo(t.params.x,t.params.y)}this.ctx.stroke()}drawLayer(t,e){if(t>e)return;const s=this.layers[t],i=this.projectIso({x:0,y:0},t);this.ctx.save(),this.ctx.scale(this.scale,this.scale),this.ctx.translate(i.x,i.y),this.ctx.rotate(this.rotation*Math.PI/180),this.ctx.translate(-this.center.x,-this.center.y),this.renderWithColor(s,t),this.ctx.restore()}render(){this.canvas.width=this.canvas.width,this.ctx.lineWidth=.6,this.ctx.scale(1,-1),this.ctx.translate(this.canvas.width/2,-this.canvas.height/2),this.center=this.getAdjustedCenter();for(let t=0;ti&&(i=t.params.x),t.params.yn&&(n=t.params.y))}return{minX:s,maxX:i,minY:r,maxY:n}}getCenter(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{x:s.minX+(s.maxX-s.minX)/2,y:s.minY+(s.maxY-s.minY)/2}}getAdjustedCenter(){const t=this.getCenter(this.layers[0]);return this.maxProjectionOffset=this.projectIso({x:0,y:0},this.layers.length-1),t.x+=this.maxProjectionOffset.x/2,t.y+=this.maxProjectionOffset.y/2,t}getSize(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{sizeX:s.maxX-s.minX,sizeY:s.maxY-s.minY}}drawBounds(t,e){this.ctx.strokeStyle=e;const{minX:s,maxX:i,minY:r,maxY:n}=this.getOuterBounds(t);console.log(s,r,i-s,n-r),this.ctx.strokeRect(s,r,i-s,n-r)}autoscale(){const{sizeX:t,sizeY:e}=this.getSize(),{width:s,height:i}=this.canvas;var r;return r=t/e>s/i?s/t:i/e,r*=.2}projectIso(t,e){return{x:t.x,y:t.y+.1*e}}},Object.defineProperty(t,"__esModule",{value:!0})}); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).GCodePreview={})}(this,function(t){"use strict";class e{constructor(t,e){this.gcode=t,this.comment=e}}class s extends e{constructor(t,e,s){super(t,s),this.params=e}}class i{constructor(t,e){this.layer=t,this.commands=e}}class n{parseCommand(t,e=!0){const i=t.trim().split(";"),n=i[0],r=e&&i[1]||null,a=n.split(/ +/g),o=a[0].toLowerCase();switch(o){case"g0":case"g1":const t=this.parseMove(a.slice(1));return new s(o,t,r);default:return null}}parseMove(t){return t.reduce((t,e)=>{const s=e.slice(0,1).toLowerCase();return"x"!=s&&"y"!=s&&"z"!=s&&"e"!=s||(t[s]=+e.slice(1)),t},{})}groupIntoLayers(t){const e=[];let n,r=0;for(const a of t.filter(t=>t instanceof s)){const t=a.params;t.z&&t.z>r&&(0!=r||t.z<2)?(r=t.z,n=new i(e.length,[a]),e.push(n)):n&&n.commands.push(a)}return e}parseGcode(t){const e=t.split("\n").filter(t=>t.length>0).map(t=>this.parseCommand(t)).filter(t=>null!==t),s=this.groupIntoLayers(e);return{header:{slicer:"MySlicer"},layers:s,limit:s.length-1}}parseHeader(t){return{slicer:t.filter(t=>null!==t.comment).map(t=>t.comment).filter(t=>/(G|g)enerated/.test(t)).map(t=>t.includes("Slic3r")?"Slic3r":t.includes("Simplify3D")?"Simplify3D":t.includes("Cura_SteamEngine")?"Cura_SteamEngine":void 0)[0]}}}t.Colors={Cura_SteamEngine:{skirt:"lime","wall-inner":"purple","wall-outer":"blue",skin:"red",fill:"orange",support:"rgba(255,255,255,0.5)"},Simplify3D:{skirt:"lime","inner perimeter":"purple","outer perimeter":"blue",skin:"solid layer",fill:"infill",support:"rgba(255,255,255,0.5)"}},t.Preview=class{constructor(t){if(this.parser=new n,this.limit=t.limit,this.scale=t.scale,this.lineWidth=t.lineWidth||.6,this.rotation=void 0===t.rotation?0:t.rotation,this.rotationAnimation=t.rotationAnimation,this.zoneColors=t.zoneColors,t.canvas instanceof HTMLCanvasElement)this.canvas=t.canvas,this.ctx=this.canvas.getContext("2d");else{this.targetId=t.targetId;const e=document.getElementById(this.targetId);if(!e)throw new Error("Unable to find element "+this.targetId);this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),e.appendChild(this.canvas),this.resize()}}clear(){this.ctx.clearRect(-this.canvas.width/2,-this.canvas.height/2,this.canvas.width,this.canvas.height)}resize(){this.canvas.width=this.canvas.parentNode.offsetWidth,this.canvas.height=this.canvas.offsetHeight}renderWithColor(t,e,s){if(s)this.ctx.strokeStyle=s;else{const t=Math.round(e/this.layers.length*80);this.ctx.strokeStyle="hsl(0, 0%, "+t+"%)"}this.ctx.beginPath();for(const e of t.commands)if("g0"==e.gcode){const t=e;this.ctx.moveTo(t.params.x,t.params.y)}else if("g1"==e.gcode){const t=e;t.params.e>0?this.ctx.lineTo(t.params.x,t.params.y):this.ctx.moveTo(t.params.x,t.params.y)}this.ctx.stroke()}drawLayer(t,e){if(t>e)return;const s=this.layers[t],i=this.projectIso({x:0,y:0},t);this.ctx.save(),this.ctx.scale(this.scale,this.scale),this.ctx.translate(i.x,i.y),this.ctx.rotate(this.rotation*Math.PI/180),this.ctx.translate(-this.center.x,-this.center.y),this.renderWithColor(s,t),this.ctx.restore()}render(){this.canvas.width=this.canvas.width,this.ctx.lineWidth=this.lineWidth,this.ctx.scale(1,-1),this.ctx.translate(this.canvas.width/2,-this.canvas.height/2),this.center=this.getAdjustedCenter();for(let t=0;ti&&(i=t.params.x),t.params.yr&&(r=t.params.y))}return{minX:s,maxX:i,minY:n,maxY:r}}getCenter(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{x:s.minX+(s.maxX-s.minX)/2,y:s.minY+(s.maxY-s.minY)/2}}getAdjustedCenter(){const t=this.getCenter(this.layers[0]);return this.maxProjectionOffset=this.projectIso({x:0,y:0},this.layers.length-1),t.x+=this.maxProjectionOffset.x/2,t.y+=this.maxProjectionOffset.y/2,t}getSize(t){const e=t||this.layers[0],s=this.getOuterBounds(e);return{sizeX:s.maxX-s.minX,sizeY:s.maxY-s.minY}}drawBounds(t,e){this.ctx.strokeStyle=e;const{minX:s,maxX:i,minY:n,maxY:r}=this.getOuterBounds(t);console.log(s,n,i-s,r-n),this.ctx.strokeRect(s,n,i-s,r-n)}autoscale(){const{sizeX:t,sizeY:e}=this.getSize(),{width:s,height:i}=this.canvas;var n;return n=t/e>s/i?s/t:i/e,n*=.2}projectIso(t,e){return{x:t.x,y:t.y+.1*e}}},Object.defineProperty(t,"__esModule",{value:!0})}); diff --git a/src/gcode-preview.ts b/src/gcode-preview.ts index 2eeeca2b..23275dde 100644 --- a/src/gcode-preview.ts +++ b/src/gcode-preview.ts @@ -6,18 +6,20 @@ export { Colors }; type PreviewOptions = Partial<{ limit: number, scale: number, + lineWidth: number, rotation: number, rotationAnimation: boolean, zoneColors: boolean, canvas: HTMLCanvasElement | string, targetId: string }> -export class Preview { +export class Preview implements PreviewOptions { limit : number rotation : number - rotationAnimation : Boolean + lineWidth : number + rotationAnimation : boolean scale : number - zoneColors : Boolean + zoneColors : boolean canvas : HTMLCanvasElement ctx : CanvasRenderingContext2D targetId: string @@ -31,26 +33,27 @@ export class Preview { maxProjectionOffset : {x:number, y:number} constructor(opts: PreviewOptions) { - this.limit = opts.limit; - this.scale = opts.scale; - this.rotation = opts.rotation === undefined ? 0 : opts.rotation; - this.rotationAnimation = opts.rotationAnimation; - this.zoneColors = opts.zoneColors; - - if (opts.canvas instanceof HTMLCanvasElement) { - this.canvas = opts.canvas; - this.ctx = this.canvas.getContext('2d'); - } - else - { - this.targetId = opts.targetId; - const target = document.getElementById(this.targetId); - if (!target) throw new Error('Unable to find element ' + this.targetId); - this.canvas = document.createElement('canvas'); - this.ctx = this.canvas.getContext('2d'); - target.appendChild(this.canvas); - this.resize(); - } + this.limit = opts.limit; + this.scale = opts.scale; + this.lineWidth = opts.lineWidth || 0.6; + this.rotation = opts.rotation === undefined ? 0 : opts.rotation; + this.rotationAnimation = opts.rotationAnimation; + this.zoneColors = opts.zoneColors; + + if (opts.canvas instanceof HTMLCanvasElement) { + this.canvas = opts.canvas; + this.ctx = this.canvas.getContext('2d'); + } + else + { + this.targetId = opts.targetId; + const target = document.getElementById(this.targetId); + if (!target) throw new Error('Unable to find element ' + this.targetId); + this.canvas = document.createElement('canvas'); + this.ctx = this.canvas.getContext('2d'); + target.appendChild(this.canvas); + this.resize(); + } } clear() { @@ -128,7 +131,7 @@ export class Preview { render() { // reset this.canvas.width = this.canvas.width; - this.ctx.lineWidth = 0.6; + this.ctx.lineWidth = this.lineWidth; // if (!this.scale) // this.scale = this.autoscale();