javascript - 在响应式画布上绘图时光标和绘图之间的间隙
问题描述
我一直在寻找解决方案几个小时,但找不到适合我的解决方案。我希望你能帮助我。
我有一个画布可以画(铅笔、线条、矩形、圆圈)。当我缩小窗口时,画布变小,并且在我绘图时鼠标光标和画布上的绘图之间存在间隙。结果是正确的,绘图的最终结果是我的鼠标光标实际所在的位置,但是在绘图时它显示了错误的位置和大小,就像它在全屏上一样。
由于结果是正确的,但过程显示错误,我真的不知道代码的哪一部分可能会受到影响,并负责显示绘图,直到您释放鼠标按钮。也许鼠标移动?如果您需要更多代码,请告诉我并感谢您的帮助!
/* 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 <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
<form action="#">
<input id="color" type="color" name="color" value="#000000">
</form>
</label>
</div>
<div class="linienstärke">
<label>Linienstärke
<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>
解决方案
imageTemp 和 imageView 没有相同的 CSS(宽度:100%)
imageTemp
canvas 被创建并附加到您的容器中,而没有考虑到您imageView
应用了特定的 CSS 属性。因此,当您调整窗口大小时,只会调整您imageView
的大小而您imageTemp
不会(因为您从未指定 100% 宽度)
临时工作修复:
我复制并粘贴了您的imageView
css 并将其应用于您的imageTemp
,以模仿相同的大小。
#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%;
}
然而
这并不能完全解决您的问题,因为尺寸不是 100% 相同(误差很小,可能不会被注意到)。我建议您使用 imageTemp css 或使用
window.addEventListener("resize", ()=>{
const canvas = document.getElementById("imageTemp");
const canvaso = document.getElementById("imageView");
canvas.width = canvaso.width;
canvas.height = canvaso.height;
}, false);
使用额外的 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 <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
<form action="#">
<input id="color" type="color" name="color" value="#000000">
</form>
</label>
</div>
<div class="linienstärke">
<label>Linienstärke
<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>
推荐阅读
- json - 禁用 Wildfly 启动日志
- java - 如何在fireabse中获取图片的下载地址?
- c# - 三元运算符错误:运算符的潜在误用?
- python - scrapy,更改 amazon.de 的位置不起作用
- reactjs - 为什么我会收到此错误?错误:第一个参数是必需的,并且必须是or
- php - 使用 Ghostscript 转换时出现 PDF 错误
- python - 根据索引“月”和列将 DataFrame 值映射到另一个 DataFrame
- spring - Junit mockito when(..).thenReturn() NullPointerException
- snowflake-cloud-data-platform - 带有自定义电子邮件的资源监视器
- kivy - 缩进无效,必须是8个空格的倍数,圆角按钮kivy .kv文件