Skip to content
Snippets Groups Projects
draw.ts 17.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • // require() is ES5 and allows modifying global variables
    // ES6's `from` does not
    import G = require("./globals");
    import * as $ from "jquery";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    import Dygraph from "dygraphs";
    
    //la funzione drawImg disegna il canvas con l'immagine desiderata ed è responsabile
    //della gestione di tutti gli eventi ad essa associati
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    export function drawImg(image: G.Image, pixel1: G.coordinates, pixel2: G.coordinates, xMinRange: number, xMaxRange: number)
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    {
    
      //alert("disegno in corso");
    
      //numero di pixel per dimensione
    
      let nPixelX: number = pixel2.x - pixel1.x + 1;
      let nPixelY: number = pixel2.y - pixel1.y + 1;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    
      //dimensione dei canvas
      let mappaPannelDim: any = document.querySelector('#mappa-pannel').getBoundingClientRect();
      let mappaWidth: number = mappaPannelDim.right - mappaPannelDim.left - 40;
      let mappaHeigth: number = 400;
    
      //dimensione reale dei pixel
      let dimPixelx: number = Math.floor(mappaWidth / nPixelX);
      let dimPixely: number = Math.floor(mappaHeigth / nPixelY);
    
      G.pixelDim = (dimPixelx < dimPixely) ? dimPixelx : dimPixely;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    
      //dimensioni esatte dei canvas
    
      (<HTMLCanvasElement>document.getElementById("myCanvas")).height = nPixelY * G.pixelDim;
      (<HTMLCanvasElement>document.getElementById("myCanvas")).width = nPixelX * G.pixelDim;
      (<HTMLCanvasElement>document.getElementById("selectionCanvas")).height = nPixelY * G.pixelDim;
      (<HTMLCanvasElement>document.getElementById("selectionCanvas")).width = nPixelX * G.pixelDim;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      let ctx = (<HTMLCanvasElement>document.getElementById('myCanvas')).getContext('2d'); //contesto del canvas
    
    
      if (xMaxRange - xMinRange >= G.channelDepth) { //range completo
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        let max: number; //massimo relativo o assoluto
    
        if (G.rePrint) {
          max = G.findMax(G.nOfCounts, pixel1, pixel2);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        } else {
    
          max = G.maxAbsolute;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        }
        max = (max * $("#SaturationSlider").val()) / 100;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawCanvas(image, G.nOfCounts, max);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    
      } else { //range parziale (solo alcuni canali)
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        let xMinRangeCh: number = Math.floor((((xMinRange * 1000) + G.Image.calibration.b) / G.Image.calibration.a) - 1); //16
        let xMaxRangeCh: number = Math.floor((((xMaxRange * 1000) + G.Image.calibration.b) / G.Image.calibration.a) - 1); //16371
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        //calcolo il numero di conteggi solo dei canali selezionati
        let nOfCountsRelative: number[][];
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        nOfCountsRelative = new Array(image.width);
        for (let i: number = 0; i < image.width; i++) {
          nOfCountsRelative[i] = new Array(image.height);
          for (let j: number = 0; j < image.height; j++) {
            nOfCountsRelative[i][j] = G.sumVect(image.DataMatrix[i][j], xMinRangeCh, xMaxRangeCh);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          }
        }
        //calcolo il massimo
        let max: number;
    
        if (G.rePrint) {
          max = G.findMax(nOfCountsRelative, pixel1, pixel2);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        } else {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          max = G.findMax(nOfCountsRelative, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 });
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        }
        max = (max * $("#SaturationSlider").val()) / 100;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawCanvas(image, nOfCountsRelative, max);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      }
    
      //La funzione, ricevuti dati e massimo, disegna la mappa nel canvas
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      function drawCanvas(image: G.Image, noc, max)
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      {
    
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        //controllo il valore della trasparenza
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        let setTrsp: number = 1 - ($("#TrasparencySlider").val() / 100);
        //let setTrsp: number = 1-(parseInt($("#TrasparencySlider").attr("value"))/100);
    
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        //scorro tutti i pixel: ne determino il colore e li disegno
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        let color: string = "";
    
        for (let i: number = pixel1.x; i <= pixel2.x; i++) {
          for (let j: number = pixel1.y; j <= pixel2.y; j++) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            let intensity: number = noc[i][j] / max;
            if (intensity < 1 / 5) //blu
              color = "rgba(0, 0, " + Math.floor(intensity * 5 * 255) + "," + setTrsp + ")";
            else if (1 / 5 <= intensity && intensity < 2 / 5) //blu+verde
              color = "rgba(0, " + Math.floor((intensity - 1 / 5) * 5 * 255) + ",255, " + setTrsp + ")";
            else if (2 / 5 <= intensity && intensity < 3 / 5) // verde-blu
              color = "rgba(0, 255, " + (255 - Math.floor((intensity - 2 / 5) * 5 * 255)) + ", " + setTrsp + ")";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            else if (3 / 5 <= intensity && intensity < 4 / 5) //verde + rosso
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
              color = "rgba(" + Math.floor((intensity - 3 / 5) * 5 * 255) + ",255,0," + setTrsp + ")";
            else //rosso -verde
              color = "rgba(255," + (255 - Math.floor((intensity - 4 / 5) * 5 * 255)) + ", 0, " + setTrsp + ")";
            ctx.fillStyle = color;
    
            ctx.fillRect((i - pixel1.x) * G.pixelDim, (j - pixel1.y) * G.pixelDim, G.pixelDim, G.pixelDim);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          }
        }
    
        G.rePrint = false; //annullo rePrint
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        zoomRect();
      }
    
      $("#SaturationSlider").mouseup(function ()
      { //Slider della saturazione
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
    
      $("#rePlot").click(function ()
      { //bottone per colorare con il max relativo
    
        G.rePrint = true;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        (<HTMLInputElement>document.getElementById("SaturationSlider")).value = "100";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
    
      $("#TrasparencySlider").mouseup(function ()
      { //Slider della trasparenza
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
    
      $("#reset").click(function ()
      { //bottone per il reset dell'applicazione
    
        G.newOrigin = { x: 0, y: 0 };
        G.rePrint = false;
        G.calibrated = false;
        G.globalxMinRange = 0;
        G.globalxMaxRange = G.channelDepth;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        (<HTMLInputElement>document.getElementById("SaturationSlider")).value = "100";
        (<HTMLInputElement>document.getElementById("TrasparencySlider")).value = "0";
        document.getElementById("spinBoxMin").setAttribute("value", "-");
        document.getElementById("spinBoxMax").setAttribute("value", "-");
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, G.channelDepth);
        drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, G.channelDepth);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
    
      $("#ExportImage").click(function ()
      { //esportazione immagine
        let img = (<HTMLCanvasElement>document.getElementById("myCanvas")).toDataURL("image/png");
        $("#ExportLink").attr("href", img);
        //document.write('<img src="'+img+'"/>');
      });
    
    }
    
    //la funzione drawChart (input: estremi dell'immagine, estremi dell'intervallo)
    //disegna il grafico richiesto relativo alla mappa visualizzata
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    export function drawChart(image: G.Image, pixel1: G.coordinates, pixel2: G.coordinates, xMinRange: number, xMaxRange: number)
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
    {
    
      //definisco la variabile "grafico", i bottoni relativi al grafico, il tag
      //select e le due spinbox con il relativo botton
      let g: any;
      let box1 = <HTMLElement>document.getElementById("spinBoxMin");
      let box2 = <HTMLElement>document.getElementById("spinBoxMax");
    
      //disegno il grafico completo
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      if (pixel1.x == 0 && pixel1.y == 0 && pixel2.x == image.width - 1 && pixel2.y == image.height - 1) {
    
        if (!G.calibrated) { //canali
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          let chartTitle: string = "Chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
    
          g = setChart(G.dataCompleteChart, chartTitle);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        } else { //energie
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          let chartTitle: string = "Calibrated chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
    
          g = setChart(G.dataCompleteChartCalibrated, chartTitle);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        }
    
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        //disegno il grafico parzialmente
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      } else {
        //determino i conteggi dei pixel da disegnare
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        let dataForChart: number[] = new Array(G.Image.depth);
        for (let i: number = 0; i < G.Image.depth; i++) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          dataForChart[i] = 0;
        }
    
        for (let i: number = pixel1.x; i <= pixel2.x; i++) {
          for (let j: number = pixel1.y; j <= pixel2.y; j++) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            for (let k: number = 0; k < G.Image.depth; k++) {
              dataForChart[k] += image.DataMatrix[i][j][k];
    
        if (!G.calibrated) { //disegno in canali
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          let dataChart: string = "Channel,Counts\n";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          for (let i: number = 0; i < G.Image.depth; i++) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            dataChart += i + "," + dataForChart[i] + "\n";
          }
          let chartTitle: string;
    
          if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            chartTitle = "Chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          } else {
    
            chartTitle = "Chart from (" + pixel1.x + "," + pixel2.x + ") to (" +
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
              (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          }
          g = setChart(dataChart, chartTitle);
    
        } else { //disegno in energie
          let dataChartCalibrated: string = "Energy,Counts\n";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          for (let i: number = 0; i < G.Image.depth; i++) {
            dataChartCalibrated += G.round3(((i + 1) * G.Image.calibration.a - G.Image.calibration.b) / 1000) + "," + dataForChart[i] + "\n";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          }
          let chartTitle: string;
    
          if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            chartTitle = "Calibrated chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          } else {
    
            chartTitle = "Calibrated chart from (" + pixel1.x + ", " + pixel2.x +
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
              ") to (" + (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          }
          g = setChart(dataChartCalibrated, chartTitle);
        }
      }
    
      $('#setlinearButton').on('click', function ()
      { //selezione scala lineare
        g.updateOptions({ logscale: false });
      });
      $('#setlogButton').on('click', function ()
      { //selezione scala logaritmica
        g.updateOptions({ logscale: true });
      });
      $('#setEnergyButton').on('click', function ()
      { //selezione energie
    
        G.calibrated = true;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawChart(image, pixel1, pixel2, 0, G.channelDepth);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        box1.setAttribute("value", "0");
    
        box2.setAttribute("value", "G.channelDepth");
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
      $('#setChannelsButton').on('click', function ()
      { //selezione canali
    
        G.calibrated = false;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawChart(image, pixel1, pixel2, 0, G.channelDepth);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        box1.setAttribute("value", "-");
        box2.setAttribute("value", "-");
      });
      $('#ExportGraph').on('click', function ()
      { //esportazione grafico
        let img = <HTMLImageElement>document.getElementById("chartToImg");
        Dygraph.Export.asPNG(g, img);
        $("#ExportGraph").attr("href", img.src.replace('image/png', 'image/octet-stream'));
      });
      $('#readSpinbox').on('click', function ()
      { //esportazione grafico
        peackSelection(0, 0);
      });
      $('#chart').on('click', function ()
      { //zoom manuale sul grafico
        let r: number[];
        r = g.xAxisRange();
    
        if (!G.calibrated) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          r[0] = Math.floor((((r[0] + 1) * G.Image.calibration.a) - G.Image.calibration.b) / 1000);
          r[1] = Math.floor((((r[1] + 1) * G.Image.calibration.a) - G.Image.calibration.b) / 1000);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        } else {
    
          r[0] = G.round3(r[0]);
          r[1] = G.round3(r[1]);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          box1.setAttribute("value", r[0].toString());
          box2.setAttribute("value", r[1].toString());
        }
    
        G.globalxMinRange = r[0];
        G.globalxMaxRange = r[1];
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, pixel1, pixel2, r[0], r[1]);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      });
      $('#elementSelect').on('change', function ()
      { //selezione elemento
        let element: string = (<HTMLInputElement>document.getElementById("elementSelect")).value;
        switch (element) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          case "1": //Ca
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            peackSelection(3.6, 3.8);
            box1.setAttribute("value", "3.60");
            box2.setAttribute("value", "3.80");
            break;
          case "2": //Pb
            peackSelection(10.4, 10.7);
            box1.setAttribute("value", "10.40");
            box2.setAttribute("value", "10.70");
            break;
          case "3":  //Hg
            peackSelection(9.8, 10.15);
            box1.setAttribute("value", "9.80");
            box2.setAttribute("value", "10.15");
            break;
          case "4": //Fe
            peackSelection(6.3, 6.5);
            box1.setAttribute("value", "6.30");
            box2.setAttribute("value", "6.50");
            break;
          case "5":  //Cu
            peackSelection(7.85, 8.2);
            box1.setAttribute("value", "7.85");
            box2.setAttribute("value", "8.20");
            break;
          case "6": //Zn
            peackSelection(8.5, 8.72);
            box1.setAttribute("value", "8.50");
            box2.setAttribute("value", "8.72");
            break;
          case "7": //Ti
            peackSelection(4.35, 4.65);
            box1.setAttribute("value", "4.35");
            box2.setAttribute("value", "4.65");
            break;
          case "8": //K
            peackSelection(3.2, 3.42);
            box1.setAttribute("value", "3.20");
            box2.setAttribute("value", "3.42");
            break;
          case "9": //Co
            peackSelection(6.8, 7.05);
            box1.setAttribute("value", "6.80");
            box2.setAttribute("value", "7.05");
            break;
          default:
    
            peackSelection(0, G.channelDepth);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            box1.setAttribute("value", "0");
    
            box2.setAttribute("value", "G.channelDepth");
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
            break;
        }
      });
    
      //la funzione setChart riceve in input i dati e il titolo del grafico da disegnare
      //il quale è restituito il output
      function setChart(dataString: string, charTitle: string)
      {
    
        let xArrayRange: number[]; //estremi asse x da visualizzare
        let xLab: string;
    
        if (!G.calibrated) {
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          xArrayRange = [0, G.Image.depth];
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
          xLab = "ADC Channel";
        } else {
          xArrayRange = [xMinRange, xMaxRange];
          xLab = "Energy (keV)";
        }
    
        //dimensioni grafico
        let chartDim: any = document.querySelector('#chart-pannel').getBoundingClientRect();
        let chartWidth = chartDim.right - chartDim.left - 50;
        $('#chart').css('width', chartWidth);
        $('#chart').css('height', "400");
    
        //disegno il grafico
        let graphs: any = new Dygraph(document.getElementById("chart"), dataString, {
          title: charTitle,
          ylabel: 'Counts',
          xlabel: xLab,
          //legend: 'always',
          labelsDivStyles: { 'textAlign': 'right' },
          dateWindow: xArrayRange,
          showRangeSelector: true,
          logscale: false
        });
    
        return graphs;
    
      }
    
      //la funzione, dati gli estremi dell'intervallo da rappresentare, aggiorna mappa e grafico
      function peackSelection(xMinRange: number, xMaxRange: number)
      {
    
        //se l'intervallo è [0, 0] devo leggere dalle i valori dalle spinbox
        if (xMinRange == 0 && xMaxRange == 0) {
          xMinRange = parseInt((<HTMLInputElement>box1).value);
          xMaxRange = parseInt((<HTMLInputElement>box2).value);
        }
    
    
        G.globalxMinRange = xMinRange;
        G.globalxMaxRange = xMaxRange;
        G.newOrigin = { x: 0, y: 0 };
        G.rePrint = false;
        G.calibrated = true;
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        drawImg(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, G.globalxMinRange, G.globalxMaxRange);
        drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, G.globalxMinRange, G.globalxMaxRange);
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
      }
    }
    
    //la funzione disegna il rettangolo durante la selezione di un'area della mappa
    function zoomRect()
    {
      let selectCanvas = <HTMLCanvasElement>document.getElementById("selectionCanvas");
      let ctx = selectCanvas.getContext("2d");
    
      // style the context
      ctx.fillStyle = "rgba(0, 110, 255, 0.25)";
    
      // this flage is true when the user is dragging the mouse
      let isDown = false;
    
      // these vars will hold the starting mouse position
      let startX: number;
      let startY: number;
      let mouseX: number;
      let mouseY: number;
    
      // these vars will hold the starting mouse position
    
      function handleMouseDown(e)
      {
        e.preventDefault();
        e.stopPropagation();
    
        //calculate mouse position
        let scrollTOP: number = (document.documentElement.scrollTop) ?
          document.documentElement.scrollTop : document.body.scrollTop;
        let scrollLEFT: number = (document.documentElement.scrollLeft) ?
          document.documentElement.scrollLeft : document.body.scrollLeft;
        let allX: number = e.clientX + scrollLEFT;
        let allY: number = e.clientY + scrollTOP;
        let elParent: any = document.getElementById('myCanvas');
        let objX: number = 0, objY: number = 0;
        while (elParent) {
          objX += elParent.offsetLeft;
          objY += elParent.offsetTop;
          elParent = elParent.offsetParent;
        }
        startX = allX - objX;
        startY = allY - objY;
    
        // set a flag indicating the drag has begun
        isDown = true;
      }
    
      function handleMouseUp(e)
      {
        e.preventDefault();
        e.stopPropagation();
    
        // the drag is over, clear the dragging flag
        isDown = false;
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
      }
    
      function handleMouseOut(e)
      {
        e.preventDefault();
        e.stopPropagation();
    
        // the drag is over, clear the dragging flag
        isDown = false;
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
      }
    
      function handleMouseMove(e)
      {
        e.preventDefault();
        e.stopPropagation();
    
        // if we're not dragging, just return
        if (!isDown) { return; }
    
        //calculate mouse position
        let scrollTOP: number = (document.documentElement.scrollTop) ?
          document.documentElement.scrollTop : document.body.scrollTop;
        let scrollLEFT: number = (document.documentElement.scrollLeft) ?
          document.documentElement.scrollLeft : document.body.scrollLeft;
    
        let allX: number = e.clientX + scrollLEFT;
        let allY: number = e.clientY + scrollTOP;
        let elParent: any = document.getElementById('myCanvas');
        let objX: number = 0, objY: number = 0;
        while (elParent) {
          objX += elParent.offsetLeft;
          objY += elParent.offsetTop;
          elParent = elParent.offsetParent;
        }
        mouseX = allX - objX;
        mouseY = allY - objY;
    
        // Put your mousemove stuff here
    
        // clear the canvas
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
    
        // calculate the rectangle width/height based
        // on starting vs current mouse position
        let width = mouseX - startX;
        let height = mouseY - startY;
    
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        // draw a new rect from the start position
    
    Francesco Giacomini's avatar
    Francesco Giacomini committed
        // to the current mouse position
        ctx.fillRect(startX, startY, width, height);
    
      }
    
      // listen for mouse events
      $("#selectionCanvas").mousedown(function (e) { handleMouseDown(e); });
      $("#selectionCanvas").mousemove(function (e) { handleMouseMove(e); });
      $("#selectionCanvas").mouseup(function (e) { handleMouseUp(e); });
      $("#selectionCanvas").mouseout(function (e) { handleMouseOut(e); });
    
    }