Search code examples
javascriptcanvascursordrawingresponsive

Gap between cursor and drawing WHEN drawing on responsive canvas


I have been searching for a solution for hours but yet can't find one that works for me. I hope you can help me.

I've got a canvas to draw on (pencil, lines, rectangles, circles). When I reduce the window, the canvas gets smaller and there is a gap between the mouse cursor and the drawing on the canvas when I am drawing. The result is right and the final product of drawing is where my mouse cursor actually was, but at the time of drawing it shows a wrong position and size, like as if it was on full screen.

Since the result is right, but the process is displayed wrong, I don't really know what part of the code might be affected and is responsible to show the drawing until you release the mouse button. Maybe mousemove? If you need any more code please let me know and thanks for any help!

/* Grundstruktur: © 2009 ROBO Design
 * http://www.robodesign.ro
 */

// Funktion wird bei Laden des Fensters aufgerufen
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context, canvaso, contexto;

  // Aktive Werkzeug-Instanz
  var tool;
  var tool_default = 'line';

  function init () {
    // Canvas Element aus HTML-Dokument abrufen
    canvaso = document.getElementById('imageView');
    if (!canvaso) {
      alert('Error: I cannot find the canvas element!');
      return;
    }

    if (!canvaso.getContext) {
      alert('Error: no canvas.getContext!');
      return;
    }

    // 2D Canvas Kontext abrufen
    contexto = canvaso.getContext('2d');
    if (!contexto) {
      alert('Error: failed to getContext!');
      return;
    }

    // Temporäres Canvas hinzufügen
    var container = canvaso.parentNode;
    canvas = document.createElement('canvas');
    if (!canvas) {
      alert('Error: I cannot create a new canvas element!');
      return;
    }

    canvas.id     = 'imageTemp';
    canvas.width  = canvaso.width;
    canvas.height = canvaso.height;
    container.appendChild(canvas);

    context = canvas.getContext('2d');

    // Eingabe für Werkzeugauswahl abrufen
    var tool_select = document.getElementById('dtool');
    if (!tool_select) {
      alert('Error: failed to get the dtool element!');
      return;
    }
    tool_select.addEventListener('change', ev_tool_change, false);

    // Standardwerkzeug aktivieren
    if (tools[tool_default]) {
      tool = new tools[tool_default]();
      tool_select.value = tool_default;
    }

    // EventListeners für mousedown, mousemove und mouseup
    canvas.addEventListener('mousedown', ev_canvas, false);
    canvas.addEventListener('mousemove', ev_canvas, false);
    canvas.addEventListener('mouseup',   ev_canvas, false);
  }

  // Allgemeiner Ereignishandler. Funktion bestimmt die Mausposition im Verhältnis zum Canvas Element.
  


  function ev_canvas (ev) {
    if (ev.layerX || ev.layerX == 0) { 
      
	  
	var rect = document.getElementById('imageView').getBoundingClientRect();
 
    var X = (ev.clientX - rect.left) / (document.getElementById('imageView').clientWidth / document.getElementById('imageView').width);
    var Y = (ev.clientY - rect.top) / (document.getElementById('imageView').clientHeight / document.getElementById('imageView').height);
    ev._x = Math.ceil(X);
    ev._y = Math.ceil(Y);
 
    } 

    // Ereignishandler des Werkzeugs aufrufen.
    var func = tool[ev.type];
    if (func) {
      func(ev);
    }
  }

  // Ereignishandler für Änderungen an der Werkzeugauswahl.
  function ev_tool_change (ev) {
    if (tools[this.value]) {
      tool = new tools[this.value]();
    }
  }

  // Funktion malt #imageTemp Canvas auf dem #imageView Canvas, danach wird #imageTemp
  // geleert. Funktion wird immer aufgerufen, wenn der Nutzer eine Zeichenoperation vervollständigt.
  function img_update () {
		contexto.drawImage(canvas, 0, 0);
		context.clearRect(0, 0, canvas.width, canvas.height);
  }

  // Objekt für die Implementierung jedes Zeichenwerkzeugs
  var tools = {};

  // Stift
  tools.pencil = function () {
    var tool = this;
    this.started = false;

    // Maustaste anfangen zu drücken
    // Stift fängt an zu malen
    this.mousedown = function (ev) {
        context.beginPath();
        context.moveTo(ev._x, ev._y);
        tool.started = true;
    };

    // Mausbewegung (tool.started muss true sein, also Maustaste gedrückt)
    this.mousemove = function (ev) {
		var color=document.getElementById ("color").value;
		context.strokeStyle = color;
		var stärke=document.getElementById ("stärke").value;
		context.lineWidth = stärke;
		context.lineCap = 'round';
      if (tool.started) {
        context.lineTo(ev._x, ev._y);
        
		
		context.stroke();
      }
    };

    // Maustaste wieder loslassen
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
        img_update();
      }
    };
  };

  // Rechteck
  tools.rect = function () {
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) {
      tool.started = true;
      tool.x0 = ev._x;
      tool.y0 = ev._y;
    };

    this.mousemove = function (ev) {
      if (!tool.started) {
        return;
      }
	
	// Variablen, um die Breite und Höhe zu ermitteln
      var x = Math.min(ev._x,  tool.x0),
          y = Math.min(ev._y,  tool.y0),
          w = Math.abs(ev._x - tool.x0),
          h = Math.abs(ev._y - tool.y0);

      context.clearRect(0, 0, canvas.width, canvas.height);

      if (!w || !h) {
        return;
      }

      
	  // Farbe, Ausgefüllt und Linienstärke werden abgerufen
	  var color=document.getElementById ("color").value;
	  var ausgefüllt=document.getElementById ("ausgefüllt").checked;
	  var stärke=document.getElementById ("stärke").value;
	  
	  // Wenn Häkchen bei ausgefüllt, dann fill, ansonsten stroke (also nur Umrandung)
	  if (ausgefüllt) {
		context.fillStyle = color;
		context.fillRect(x, y, w, h);
	  }
	  else {
		context.strokeStyle = color;
		context.lineWidth = stärke;
		context.strokeRect(x, y, w, h);
	  }
		
		
		
		
    };

    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
        img_update();
      }
    };
	
	

		
  };
  
  
  // Das Kreiswerkzeug
  
  tools.arc = function () {
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) {
      tool.started = true;
      tool.x0 = ev._x;
      tool.y0 = ev._y;
    };

    this.mousemove = function (ev) {
      if (!tool.started) {
        return;
      }

	  //Hinzufügen von r als Radius, Satz des Pythagoras
	  //ev._x und ev._y : Mausposition nach Bewegung
	  //tool.x0 und tool.y0 : Mausposition, wenn man anfängt zu klicken (vor der Bewegung)
	  //sqrt : Wurzel --> Wurzel aus a² + b²
      var x = Math.min(ev._x, tool.x0),
          y = Math.min(ev._y, tool.y0),
		  r = Math.sqrt((ev._x - tool.x0)*(ev._x - tool.x0) + (ev._y - tool.y0)*(ev._y - tool.y0))

      context.clearRect(0, 0, canvas.width, canvas.height);

    var color=document.getElementById ("color").value;
	var ausgefüllt=document.getElementById ("ausgefüllt").checked;
	var stärke=document.getElementById ("stärke").value;
	
	//arc zeichnet Bogen, 2*Math.PI ergibt dann einen vollständigen Kreis
	if (ausgefüllt) {
		context.beginPath();
		context.fillStyle = color;
		context.arc(x, y, r, 0, 2 * Math.PI, false);
		context.fill();
	  	
	}
	
	else {
		context.beginPath();
		context.strokeStyle = color;
		context.lineWidth = stärke;
		context.arc(x, y, r, 0, 2 * Math.PI, false);
		context.stroke();
	  }
		
    };

    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
        img_update();
      }
    };
	
	

		
  };
	  
	  

  // Das Linien-Werkzeug
  tools.line = function () {
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) {
      tool.started = true;
      tool.x0 = ev._x;
      tool.y0 = ev._y;
    };

    this.mousemove = function (ev) {
      if (!tool.started) {
        return;
      }

      context.clearRect(0, 0, canvas.width, canvas.height);

	  // Mausposition wird nach tool.x0 und tool.y0 (x- und y-Wert des Mauszeigers) versetzt 
	  //(dort beginnt die Linie), Linie wird dann nach ev._x und ev._y gezogen (x- und y-Wert
	  //wenn Bewegung der Maus vollzogen)
      context.beginPath();
      context.moveTo(tool.x0, tool.y0);
      context.lineTo(ev._x,   ev._y);
      
	  context.stroke();
	  var color=document.getElementById ("color").value;
		context.strokeStyle = color;
	  var stärke=document.getElementById ("stärke").value;
		context.lineWidth = stärke;
      context.closePath();
    };

	
    this.mouseup = function (ev) {
      if (tool.started) {
        tool.mousemove(ev);
        tool.started = false;
        img_update();
      }
    };
  };

  init();

}, false); }

// 


//X- und Y-Werte der Maus anzeigen (nur für Canvas-Bereich)

var info = document.getElementById('mouse-position');

this.tellPos = function (ev) {
	pageX = ev._x;
	pageY = ev._y;
  info.innerHTML = 'Position X : ' + pageX + '<br />Position Y : ' + pageY;
}
addEventListener('mousemove', tellPos, false);
	  
	  
	  
//Buttons-Funktionen

//"Speichern"
function putImage()
{
  var canvas = document.getElementById("imageView");        
  if (canvas.getContext) {
     var context = canvas.getContext("2d");                
     var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");    
  }
  var imageElement = document.getElementById("MyPix");  
  window.location.href=image;                          

}  

//Zeichenfläche leeren "Neu"
var canvas = document.getElementById('imageView');
var context = canvas.getContext('2d');
var clearCanvas = document.getElementById("clear");
clearCanvas.addEventListener("click", eraseCanvas, false);

function eraseCanvas() {
	context.clearRect(0, 0, canvas.width, canvas.height);
}

//Canvas responsiv machen
body {
    margin: 0;
}
 h1 {
         
	 color: #000000;
 }
 
 .nav-tabs {
	background-color:#FFFFFF;
}

 
.form-inline {
    display: flex;
    flex-direction: row;
    position: block;
    width: 100%;
	
}
	
.kriterien, .farbe, .linienstärke, .ausfüllen{
	margin-right: 10px;
	margin-bottom: 5px;
	font-size: 12pt;
	line-height: 10px;
	vertical-align: middle;
	background-color:#F0FFFF;
	border-color: black;
	border-width: 1px;
	border-style: solid;
	border-radius: 5px;
	padding-top: 15px;
	padding-right: 10px;
	padding-left: 10px;
	padding-bottom: 15px;
}


.mouse-position {
	position: right;
	margin-left:40px;
	margin-right: 40px;
	
}

.controls {
	margin-top: 10px;
}

#imageView {
	position: center;
	padding-left: 0;
	padding-right: 0;
	margin-left: auto;
	margin-right: auto;
	width: 100%;
}

#unterereihe {
	margin-top: 30px;
}

.form-control {
	font-size: 95%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
    <link rel="stylesheet" href="style.css">
	



<style>
#container { position: relative; }
#imageView { border: 1px solid #000; }
#imageTemp { position: absolute; top: 1px; left: 1px; }

</style>

</head>

<body>


<div class="container">

	<div class="page-header">
		<h1 class="display-3 text-center">Paint-Tool</h1>
	</div>

	<div class="container">

		

		<div>

			
		</div>
	</div>



	<form class="form-inline">
		<div class="form-group">


			<div class="kriterien">
				<label>Zeichenwerkzeug &nbsp;<select id="dtool">
					<option value="pencil">Stift</option>
					<option value="rect">Rechteck</option>						
					<option value="arc">Kreis</option>
					<option value="line">Linie</option>
				</select></label>
			</div>
	

			<div class="farbe">
				<label>Farbe &nbsp;
					<form action="#">
						<input id="color" type="color" name="color" value="#000000">
					</form>	
				</label>
			</div>


			<div class="linienstärke">
				<label>Linienstärke &nbsp;	
					<form action="#">
						<input id="stärke" type="range" name="range" value="1"min="1" max="50" value="1">
					</form>
				</label>
			</div>
	
			<div class="ausfüllen">
				<input id="ausgefüllt" name="ausgefüllt" type="checkbox" checked> Ausfüllen
			</div>
		
		
			<div id="mouse-position">
			</div>
		</div>
    </form>
	
	
	<div id="container">
		<canvas id="imageView" width="1108" height="400">
		</canvas>
	</div>
	
	<div class="controls">
		<button type="button" class="btn btn-dark" onclick="putImage()" id="save">Speichern</button>
		<button type="button" class="btn btn-dark" onclick"clear()" id="clear">Neu</button>
	</div>




<script type="text/javascript" src="paint-tool.js"></script>
  
  </body>
</html>
      



</div>










<!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
	<script src="http://hongru.github.io/proj/canvas2image/canvas2image.js"></script>
	
	
</body>
</html>


Solution

  • imageTemp and imageView do not have the same CSS (width: 100%)

    imageTemp canvas was created and appended to your container without taking in account that your imageView has specific CSS attributes applied to it. Thus when you resize the window, only your imageView gets resized and your imageTemp does not (since you never specified 100% width)

    temporary working fix: I copied and pasted your imageView css and applied it to your imageTemp, to mimic the same size.

    #imageView {
        position: center;
        padding-left: 0;
        padding-right: 0;
        margin-left: auto;
        margin-right: auto;
        width: 100%;
    }
    
    #imageTemp {
        position: center;
        padding-left: 0;
        padding-right: 0;
        margin-left: auto;
        margin-right: auto;
        width: 100%;
    }
    

    However

    This does not completely solve your problem, as the sizes are not 100% the same (very small margin of error, probably won't be noticeable). I recommend you play with your imageTemp css or work with

     window.addEventListener("resize", ()=>{
       const canvas = document.getElementById("imageTemp");
       const canvaso = document.getElementById("imageView");
       canvas.width = canvaso.width;
       canvas.height = canvaso.height;
     }, false);
    

    Updated code with the additional css

    /* Grundstruktur: © 2009 ROBO Design
     * http://www.robodesign.ro
     */
    
    // Funktion wird bei Laden des Fensters aufgerufen
    if(window.addEventListener) {
    
    window.addEventListener('load', function () {
      var canvas, context, canvaso, contexto;
    
      // Aktive Werkzeug-Instanz
      var tool;
      var tool_default = 'line';
    
      function init () {
        // Canvas Element aus HTML-Dokument abrufen
        canvaso = document.getElementById('imageView');
        if (!canvaso) {
          alert('Error: I cannot find the canvas element!');
          return;
        }
    
        if (!canvaso.getContext) {
          alert('Error: no canvas.getContext!');
          return;
        }
    
        // 2D Canvas Kontext abrufen
        contexto = canvaso.getContext('2d');
        if (!contexto) {
          alert('Error: failed to getContext!');
          return;
        }
    
        // Temporäres Canvas hinzufügen
        var container = canvaso.parentNode;
        canvas = document.createElement('canvas');
        if (!canvas) {
          alert('Error: I cannot create a new canvas element!');
          return;
        }
    
        canvas.id     = 'imageTemp';
        canvas.width  = canvaso.width;
        canvas.height = canvaso.height;
        container.appendChild(canvas);
    
        context = canvas.getContext('2d');
    
        // Eingabe für Werkzeugauswahl abrufen
        var tool_select = document.getElementById('dtool');
        if (!tool_select) {
          alert('Error: failed to get the dtool element!');
          return;
        }
        tool_select.addEventListener('change', ev_tool_change, false);
    
        // Standardwerkzeug aktivieren
        if (tools[tool_default]) {
          tool = new tools[tool_default]();
          tool_select.value = tool_default;
        }
    
        // EventListeners für mousedown, mousemove und mouseup
        canvas.addEventListener('mousedown', ev_canvas, false);
        canvas.addEventListener('mousemove', ev_canvas, false);
        canvas.addEventListener('mouseup',   ev_canvas, false);
      }
    
      // Allgemeiner Ereignishandler. Funktion bestimmt die Mausposition im Verhältnis zum Canvas Element.
      
    
    
      function ev_canvas (ev) {
        if (ev.layerX || ev.layerX == 0) { 
          
    	  
    	var rect = document.getElementById('imageView').getBoundingClientRect();
     
        var X = (ev.clientX - rect.left) / (document.getElementById('imageView').clientWidth / document.getElementById('imageView').width);
        var Y = (ev.clientY - rect.top) / (document.getElementById('imageView').clientHeight / document.getElementById('imageView').height);
        ev._x = Math.ceil(X);
        ev._y = Math.ceil(Y);
     
        } 
    
        // Ereignishandler des Werkzeugs aufrufen.
        var func = tool[ev.type];
        if (func) {
          func(ev);
        }
      }
    
      // Ereignishandler für Änderungen an der Werkzeugauswahl.
      function ev_tool_change (ev) {
        if (tools[this.value]) {
          tool = new tools[this.value]();
        }
      }
    
      // Funktion malt #imageTemp Canvas auf dem #imageView Canvas, danach wird #imageTemp
      // geleert. Funktion wird immer aufgerufen, wenn der Nutzer eine Zeichenoperation vervollständigt.
      function img_update () {
    		contexto.drawImage(canvas, 0, 0);
    		context.clearRect(0, 0, canvas.width, canvas.height);
      }
    
      // Objekt für die Implementierung jedes Zeichenwerkzeugs
      var tools = {};
    
      // Stift
      tools.pencil = function () {
        var tool = this;
        this.started = false;
    
        // Maustaste anfangen zu drücken
        // Stift fängt an zu malen
        this.mousedown = function (ev) {
            context.beginPath();
            context.moveTo(ev._x, ev._y);
            tool.started = true;
        };
    
        // Mausbewegung (tool.started muss true sein, also Maustaste gedrückt)
        this.mousemove = function (ev) {
    		var color=document.getElementById ("color").value;
    		context.strokeStyle = color;
    		var stärke=document.getElementById ("stärke").value;
    		context.lineWidth = stärke;
    		context.lineCap = 'round';
          if (tool.started) {
            context.lineTo(ev._x, ev._y);
            
    		
    		context.stroke();
          }
        };
    
        // Maustaste wieder loslassen
        this.mouseup = function (ev) {
          if (tool.started) {
            tool.mousemove(ev);
            tool.started = false;
            img_update();
          }
        };
      };
    
      // Rechteck
      tools.rect = function () {
        var tool = this;
        this.started = false;
    
        this.mousedown = function (ev) {
          tool.started = true;
          tool.x0 = ev._x;
          tool.y0 = ev._y;
        };
    
        this.mousemove = function (ev) {
          if (!tool.started) {
            return;
          }
    	
    	// Variablen, um die Breite und Höhe zu ermitteln
          var x = Math.min(ev._x,  tool.x0),
              y = Math.min(ev._y,  tool.y0),
              w = Math.abs(ev._x - tool.x0),
              h = Math.abs(ev._y - tool.y0);
    
          context.clearRect(0, 0, canvas.width, canvas.height);
    
          if (!w || !h) {
            return;
          }
    
          
    	  // Farbe, Ausgefüllt und Linienstärke werden abgerufen
    	  var color=document.getElementById ("color").value;
    	  var ausgefüllt=document.getElementById ("ausgefüllt").checked;
    	  var stärke=document.getElementById ("stärke").value;
    	  
    	  // Wenn Häkchen bei ausgefüllt, dann fill, ansonsten stroke (also nur Umrandung)
    	  if (ausgefüllt) {
    		context.fillStyle = color;
    		context.fillRect(x, y, w, h);
    	  }
    	  else {
    		context.strokeStyle = color;
    		context.lineWidth = stärke;
    		context.strokeRect(x, y, w, h);
    	  }
    		
    		
    		
    		
        };
    
        this.mouseup = function (ev) {
          if (tool.started) {
            tool.mousemove(ev);
            tool.started = false;
            img_update();
          }
        };
    	
    	
    
    		
      };
      
      
      // Das Kreiswerkzeug
      
      tools.arc = function () {
        var tool = this;
        this.started = false;
    
        this.mousedown = function (ev) {
          tool.started = true;
          tool.x0 = ev._x;
          tool.y0 = ev._y;
        };
    
        this.mousemove = function (ev) {
          if (!tool.started) {
            return;
          }
    
    	  //Hinzufügen von r als Radius, Satz des Pythagoras
    	  //ev._x und ev._y : Mausposition nach Bewegung
    	  //tool.x0 und tool.y0 : Mausposition, wenn man anfängt zu klicken (vor der Bewegung)
    	  //sqrt : Wurzel --> Wurzel aus a² + b²
          var x = Math.min(ev._x, tool.x0),
              y = Math.min(ev._y, tool.y0),
    		  r = Math.sqrt((ev._x - tool.x0)*(ev._x - tool.x0) + (ev._y - tool.y0)*(ev._y - tool.y0))
    
          context.clearRect(0, 0, canvas.width, canvas.height);
    
        var color=document.getElementById ("color").value;
    	var ausgefüllt=document.getElementById ("ausgefüllt").checked;
    	var stärke=document.getElementById ("stärke").value;
    	
    	//arc zeichnet Bogen, 2*Math.PI ergibt dann einen vollständigen Kreis
    	if (ausgefüllt) {
    		context.beginPath();
    		context.fillStyle = color;
    		context.arc(x, y, r, 0, 2 * Math.PI, false);
    		context.fill();
    	  	
    	}
    	
    	else {
    		context.beginPath();
    		context.strokeStyle = color;
    		context.lineWidth = stärke;
    		context.arc(x, y, r, 0, 2 * Math.PI, false);
    		context.stroke();
    	  }
    		
        };
    
        this.mouseup = function (ev) {
          if (tool.started) {
            tool.mousemove(ev);
            tool.started = false;
            img_update();
          }
        };
    	
    	
    
    		
      };
    	  
    	  
    
      // Das Linien-Werkzeug
      tools.line = function () {
        var tool = this;
        this.started = false;
    
        this.mousedown = function (ev) {
          tool.started = true;
          tool.x0 = ev._x;
          tool.y0 = ev._y;
        };
    
        this.mousemove = function (ev) {
          if (!tool.started) {
            return;
          }
    
          context.clearRect(0, 0, canvas.width, canvas.height);
    
    	  // Mausposition wird nach tool.x0 und tool.y0 (x- und y-Wert des Mauszeigers) versetzt 
    	  //(dort beginnt die Linie), Linie wird dann nach ev._x und ev._y gezogen (x- und y-Wert
    	  //wenn Bewegung der Maus vollzogen)
          context.beginPath();
          context.moveTo(tool.x0, tool.y0);
          context.lineTo(ev._x,   ev._y);
          
    	  context.stroke();
    	  var color=document.getElementById ("color").value;
    		context.strokeStyle = color;
    	  var stärke=document.getElementById ("stärke").value;
    		context.lineWidth = stärke;
          context.closePath();
        };
    
    	
        this.mouseup = function (ev) {
          if (tool.started) {
            tool.mousemove(ev);
            tool.started = false;
            img_update();
          }
        };
      };
    
      init();
    
    }, false); }
    
    // 
    
    
    //X- und Y-Werte der Maus anzeigen (nur für Canvas-Bereich)
    
    var info = document.getElementById('mouse-position');
    
    this.tellPos = function (ev) {
    	pageX = ev._x;
    	pageY = ev._y;
      info.innerHTML = 'Position X : ' + pageX + '<br />Position Y : ' + pageY;
    }
    addEventListener('mousemove', tellPos, false);
    	  
    	  
    	  
    //Buttons-Funktionen
    
    //"Speichern"
    function putImage()
    {
      var canvas = document.getElementById("imageView");        
      if (canvas.getContext) {
         var context = canvas.getContext("2d");                
         var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");    
      }
      var imageElement = document.getElementById("MyPix");  
      window.location.href=image;                          
    
    }  
    
    //Zeichenfläche leeren "Neu"
    var canvas = document.getElementById('imageView');
    var context = canvas.getContext('2d');
    var clearCanvas = document.getElementById("clear");
    clearCanvas.addEventListener("click", eraseCanvas, false);
    
    function eraseCanvas() {
    	context.clearRect(0, 0, canvas.width, canvas.height);
    }
    
    //Canvas responsiv machen
    body {
        margin: 0;
    }
     h1 {
             
    	 color: #000000;
     }
     
     .nav-tabs {
    	background-color:#FFFFFF;
    }
    
     
    .form-inline {
        display: flex;
        flex-direction: row;
        position: block;
        width: 100%;
    	
    }
    	
    .kriterien, .farbe, .linienstärke, .ausfüllen{
    	margin-right: 10px;
    	margin-bottom: 5px;
    	font-size: 12pt;
    	line-height: 10px;
    	vertical-align: middle;
    	background-color:#F0FFFF;
    	border-color: black;
    	border-width: 1px;
    	border-style: solid;
    	border-radius: 5px;
    	padding-top: 15px;
    	padding-right: 10px;
    	padding-left: 10px;
    	padding-bottom: 15px;
    }
    
    
    .mouse-position {
    	position: right;
    	margin-left:40px;
    	margin-right: 40px;
    	
    }
    
    .controls {
    	margin-top: 10px;
    }
    
    #imageView {
    	position: center;
    	padding-left: 0;
    	padding-right: 0;
    	margin-left: auto;
    	margin-right: auto;
    	width: 100%;
    }
    
    #imageTemp {
    	position: center;
    	padding-left: 0;
    	padding-right: 0;
    	margin-left: auto;
    	margin-right: auto;
    	width: 100%;
    }
    
    #unterereihe {
    	margin-top: 30px;
    }
    
    .form-control {
    	font-size: 95%;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
        <link rel="stylesheet" href="style.css">
    	
    
    
    
    <style>
    #container { position: relative; }
    #imageView { border: 1px solid #000; }
    #imageTemp { position: absolute; top: 1px; left: 1px; }
    
    </style>
    
    </head>
    
    <body>
    
    
    <div class="container">
    
    	<div class="page-header">
    		<h1 class="display-3 text-center">Paint-Tool</h1>
    	</div>
    
    	<div class="container">
    
    		
    
    		<div>
    
    			
    		</div>
    	</div>
    
    
    
    	<form class="form-inline">
    		<div class="form-group">
    
    
    			<div class="kriterien">
    				<label>Zeichenwerkzeug &nbsp;<select id="dtool">
    					<option value="pencil">Stift</option>
    					<option value="rect">Rechteck</option>						
    					<option value="arc">Kreis</option>
    					<option value="line">Linie</option>
    				</select></label>
    			</div>
    	
    
    			<div class="farbe">
    				<label>Farbe &nbsp;
    					<form action="#">
    						<input id="color" type="color" name="color" value="#000000">
    					</form>	
    				</label>
    			</div>
    
    
    			<div class="linienstärke">
    				<label>Linienstärke &nbsp;	
    					<form action="#">
    						<input id="stärke" type="range" name="range" value="1"min="1" max="50" value="1">
    					</form>
    				</label>
    			</div>
    	
    			<div class="ausfüllen">
    				<input id="ausgefüllt" name="ausgefüllt" type="checkbox" checked> Ausfüllen
    			</div>
    		
    		
    			<div id="mouse-position">
    			</div>
    		</div>
        </form>
    	
    	
    	<div id="container">
    		<canvas id="imageView" width="1108" height="400">
    		</canvas>
    	</div>
    	
    	<div class="controls">
    		<button type="button" class="btn btn-dark" onclick="putImage()" id="save">Speichern</button>
    		<button type="button" class="btn btn-dark" onclick"clear()" id="clear">Neu</button>
    	</div>
    
    
    
    
    <script type="text/javascript" src="paint-tool.js"></script>
      
      </body>
    </html>
          
    
    
    
    </div>
    
    
    
    
    
    
    
    
    
    
    <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
    	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    	<script src="http://hongru.github.io/proj/canvas2image/canvas2image.js"></script>
    	
    	
    </body>
    </html>