How to draw a simple ruler with JavaScript?

I am starting with PhoneGap and I am trying to use a simple application, Ruler. I start in JavaScript, most of my work with mobile phones was in native Android code, but I crack my head on it and I can’t understand what happened.

Due to the different screen sizes, my idea is to calculate how many pixels I have per millimeter (pixelsInMm), get the height of the screen and use an HTML5 canvas to draw a line every N pixels.

The body of my HTML is quite simple, the canvas fills the entire screen

<body onload="init();" id="stage" class="theme"> <canvas id="myCanvas" style="width: 100%;height: 100%;"></canvas> </body> 

I already figured out how to get the density in pixels per inch of the device (dpi) and using simple math, we can get how many pixels we have on one centimeter

 var mmInInch = 25.399999999972568; function getPixelsPerMillimeter(dpi){ return dpi/mmInInch; } 

And the rest of my js file is also simple

 var heightInPixels; var heightDensity; 

Get the height density in pixels per inch

 function getDeviceResolution(){ heightDensity = window.MyConnectorClass.getYdpi(); heightInPixels = window.outerHeight; console.log("Y density = " + heightDensity); console.log("Y pixels = " + heightInPixels); return heightDensity; } 

Draw a horizontal line in the given canvas and y coordinate

 function drawOnCanvas(ctx2d,y){ console.log("Drawing on :" + y) ctx2d.moveTo(0,y); ctx2d.lineTo(20,y); ctx2d.stroke(); } 

My main loop is where on each ppm it draws one horizontal line.

 function drawRuler(){ console.log("append Ruler") var YDpi = getDeviceResolution(); var ppm = getPixelsPerMillimeter(YDpi); var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); ctx.lineWidth = 1; for(var i=0; i<90; i++){ var topPos = (5+ i*ppm); console.log("topPos" + topPos); drawOnCanvas(ctx,topPos); }; } 

But instead of getting the expected ruler, as you can see in the image below what I get, the lines are very spaced, far from the 1 mm that I expected. What for? Also, the lines he draws are of different sizes, and they are definitely not 1px wide.

enter image description here

Here is the logarithm showing that the calculations are correct, I test this in the Galaxy S2 with a height of 800 pixels, with a screen height of 93 mm, so every 8.6 pixels I have one millimeter.

 09-22 \n:16.530: D/test(12353): ppm:8.602150744349842 09-22 \n:16.530: D/test(12353): mmSize:93.0 09-22 \n:16.530: D/test(12353): Pos0: 5.0px 09-22 \n:16.530: D/test(12353): Pos1: 13.602150744349842px 09-22 \n:16.530: D/test(12353): Pos2: 22.204301488699684px 09-22 \n:16.530: D/test(12353): Pos3: 30.806452233049527px 09-22 \n:16.530: D/test(12353): Pos4: 39.40860297739937px 09-22 \n:16.530: D/test(12353): Pos5: 48.01075372174921px 09-22 \n:16.530: D/test(12353): Pos6: 56.61290446609905px 09-22 \n:16.535: D/test(12353): Pos7: 65.2150552104489px 09-22 \n:16.535: D/test(12353): Pos8: 73.81720595479874px 09-22 \n:16.535: D/test(12353): Pos9: 82.41935669914858px 09-22 \n:16.535: D/test(12353): Pos10: 91.02150744349842px 09-22 \n:16.535: D/test(12353): Pos11: 99.62365818784826px 09-22 \n:16.535: D/test(12353): Pos12: 108.2258089321981px 09-22 \n:16.535: D/test(12353): Pos13: 116.82795967654795px 09-22 \n:16.535: D/test(12353): Pos14: 125.43011042089779px 09-22 \n:16.535: D/test(12353): Pos15: 134.03226116524763px 09-22 \n:16.540: D/test(12353): Pos16: 142.63441190959747px 09-22 \n:16.540: D/test(12353): Pos17: 151.23656265394732px 09-22 \n:16.540: D/test(12353): Pos18: 159.83871339829716px 09-22 \n:16.540: D/test(12353): Pos19: 168.440864142647px 09-22 \n:16.540: D/test(12353): Pos20: 177.04301488699684px 09-22 \n:16.540: D/test(12353): Pos21: 185.64516563134669px 09-22 \n:16.540: D/test(12353): Pos22: 194.24731637569653px 09-22 \n:16.540: D/test(12353): Pos23: 202.84946712004637px 09-22 \n:16.540: D/test(12353): Pos24: 211.4516178643962px 09-22 \n:16.540: D/test(12353): Pos25: 220.05376860874605px 09-22 \n:16.540: D/test(12353): Pos26: 228.6559193530959px 09-22 \n:16.540: D/test(12353): Pos27: 237.25807009744574px 09-22 \n:16.540: D/test(12353): Pos28: 245.86022084179558px 09-22 \n:16.540: D/test(12353): Pos29: 254.46237158614542px 09-22 \n:16.540: D/test(12353): Pos30: 263.06452233049527px 09-22 \n:16.540: D/test(12353): Pos31: 271.6666730748451px 09-22 \n:16.540: D/test(12353): Pos32: 280.26882381919495px 09-22 \n:16.540: D/test(12353): Pos33: 288.8709745635448px 09-22 \n:16.540: D/test(12353): Pos34: 297.47312530789463px 09-22 \n:16.540: D/test(12353): Pos35: 306.0752760522445px 09-22 \n:16.540: D/test(12353): Pos36: 314.6774267965943px 09-22 \n:16.540: D/test(12353): Pos37: 323.27957754094416px 09-22 \n:16.540: D/test(12353): Pos38: 331.881728285294px 09-22 \n:16.540: D/test(12353): Pos39: 340.48387902964384px 09-22 \n:16.540: D/test(12353): Pos40: 349.0860297739937px 09-22 \n:16.540: D/test(12353): Pos41: 357.68818051834353px 09-22 \n:16.540: D/test(12353): Pos42: 366.29033126269337px 09-22 \n:16.540: D/test(12353): Pos43: 374.8924820070432px 09-22 \n:16.540: D/test(12353): Pos44: 383.49463275139306px 09-22 \n:16.540: D/test(12353): Pos45: 392.0967834957429px 09-22 \n:16.545: D/test(12353): Pos46: 400.69893424009274px 09-22 \n:16.545: D/test(12353): Pos47: 409.3010849844426px 09-22 \n:16.545: D/test(12353): Pos48: 417.9032357287924px 09-22 \n:16.545: D/test(12353): Pos49: 426.50538647314227px 09-22 \n:16.545: D/test(12353): Pos50: 435.1075372174921px 09-22 \n:16.545: D/test(12353): Pos51: 443.70968796184195px 09-22 \n:16.545: D/test(12353): Pos52: 452.3118387061918px 09-22 \n:16.545: D/test(12353): Pos53: 460.91398945054164px 09-22 \n:16.545: D/test(12353): Pos54: 469.5161401948915px 09-22 \n:16.545: D/test(12353): Pos55: 478.1182909392413px 09-22 \n:16.545: D/test(12353): Pos56: 486.72044168359116px 09-22 \n:16.545: D/test(12353): Pos57: 495.322592427941px 09-22 \n:16.545: D/test(12353): Pos58: 503.92474317229085px 09-22 \n:16.545: D/test(12353): Pos59: 512.5268939166407px 09-22 \n:16.545: D/test(12353): Pos60: 521.1290446609905px 09-22 \n:16.545: D/test(12353): Pos61: 529.7311954053404px 09-22 \n:16.545: D/test(12353): Pos62: 538.3333461496902px 09-22 \n:16.545: D/test(12353): Pos63: 546.93549689404px 09-22 \n:16.545: D/test(12353): Pos64: 555.5376476383899px 09-22 \n:16.545: D/test(12353): Pos65: 564.1397983827397px 09-22 \n:16.545: D/test(12353): Pos66: 572.7419491270896px 09-22 \n:16.545: D/test(12353): Pos67: 581.3440998714394px 09-22 \n:16.545: D/test(12353): Pos68: 589.9462506157893px 09-22 \n:16.545: D/test(12353): Pos69: 598.5484013601391px 09-22 \n:16.545: D/test(12353): Pos70: 607.150552104489px 09-22 \n:16.545: D/test(12353): Pos71: 615.7527028488388px 09-22 \n:16.545: D/test(12353): Pos72: 624.3548535931886px 09-22 \n:16.545: D/test(12353): Pos73: 632.9570043375385px 09-22 \n:16.545: D/test(12353): Pos74: 641.5591550818883px 09-22 \n:16.545: D/test(12353): Pos75: 650.1613058262382px 09-22 \n:16.545: D/test(12353): Pos76: 658.763456570588px 09-22 \n:16.545: D/test(12353): Pos77: 667.3656073149378px 09-22 \n:16.545: D/test(12353): Pos78: 675.9677580592877px 09-22 \n:16.545: D/test(12353): Pos79: 684.5699088036375px 09-22 \n:16.545: D/test(12353): Pos80: 693.1720595479874px 09-22 \n:16.545: D/test(12353): Pos81: 701.7742102923372px 09-22 \n:16.545: D/test(12353): Pos82: 710.3763610366871px 09-22 \n:16.550: D/test(12353): Pos83: 718.9785117810369px 09-22 \n:16.550: D/test(12353): Pos84: 727.5806625253867px 09-22 \n:16.550: D/test(12353): Pos85: 736.1828132697366px 09-22 \n:16.550: D/test(12353): Pos86: 744.7849640140864px 09-22 \n:16.550: D/test(12353): Pos87: 753.3871147584363px 09-22 \n:16.550: D/test(12353): Pos88: 761.9892655027861px 09-22 \n:16.550: D/test(12353): Pos89: 770.591416247136px 09-22 \n:16.550: D/test(12353): Pos90: 779.1935669914858px 09-22 \n:16.550: D/test(12353): Pos91: 787.7957177358356px 09-22 \n:16.550: D/test(12353): Pos92: 796.3978684801855px 
+1
source share
2 answers

A couple of questions continue.

Take a look at http://diveintohtml5.info/canvas.html - it turns out how to avoid blurry lines (start lines at 0.5 pixels) and talk about the size of the canvas (do not do this via css).

As an example, consider here: http://jsfiddle.net/QdBd7/2/

Changes:

This captures the odd line width:

 drawOnCanvas(Math.floor(topPos)+.5) 

Added missing starting path:

 ctx.beginPath(); 

Resize canvas at boot time:

 function resizeCanvas(){ c.width = document.body.clientWidth - 5, // 5 is from jsfiddle frame c.height = document.body.clientHeight - 5; } 

Even with these changes, you still notice small changes, I do not want to point out this: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

But I have no solutions (since ppm can end with some odd y value, for example, 75.812315 - it will be .3 pixels from ...), since you draw more, you can somehow adjust the variations but it becomes even more complicated because floating point errors start to come in.

Hope you get started.

+3
source
 var cmm=15 var countCm=0 var c = document.getElementById("myCanvas"); var ctx= c.getContext("2d"); ctx.lineWidth = 1; ctx.fillRect(0,0,30,250); function drawOnCanvas(y){ ctx.beginPath(); ctx.moveTo(0,y); ctx.lineTo(cmm,y); ctx.stroke(); } function drawRuler(){ var ppm = 8.602150744349842, count = Math.floor(c.height / ppm); for(var i=0; i<count; i++){ if(countCm==4){cmm=15;countCm=0}else{cmm=4;countCm++} var topPos = (5 + i*ppm); drawOnCanvas(Math.floor(topPos)+.5); }; } function resizeCanvas(){ c.width = document.body.clientWidth - 5, c.height = document.body.clientHeight - 5; } resizeCanvas(); drawRuler(); 
-1
source

Source: https://habr.com/ru/post/1435705/


All Articles