admin管理员组文章数量:1323317
Any discussion is weled. Thanks for reading!
What I am trying to do
I'm trying to implement simple paper(whiteboard) using Konva.js.
So far I've implemented Drag, Zoom and Free drawing on paper.
I referred to
- .html for Zoom
- .html for Free drawing
I want to draw only on the region with beige color background, and I want to draw exactly under the pointer even though it is zoomed or dragged.
But Free drawing and both Drag and Zoom features don't work well together.
Bug
Can't draw correctly after dragging or zooming.
Where I think wrong thing is happening, but can't fix
I think something is wrong in the 2 parts bellow.
- Implementation of zoom
- How I use stage.getPointerPosition() in drawing implementation
- Or implementations of these two doesn't fit together
Code
Minimum code is here.
/* ---- Mode management ---- */
let modeSelector = document.getElementById('mode-selector');
let mode = modeSelector.value;
modeSelector.addEventListener('change', () => {
// Discaed event handlers used by old mode
switch (mode) {
case 'Hand': {
endHand();
break;
}
case 'Pen': {
endPen();
break;
}
}
// Set event handlers for new mode
mode = modeSelector.value;
switch (mode) {
case 'Hand': {
useHand();
break;
}
case 'Pen': {
usePen();
break;
}
}
});
/* ---- Konva Objects ---- */
let stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
// A layer that is only used for background color
let backgroundLayer = new Konva.Layer();
let backgroundColor = new Konva.Image({
width: window.innerWidth,
height: window.innerHeight,
fill: 'rgb(242,233,226)'
})
backgroundLayer.add(backgroundColor);
stage.add(backgroundLayer);
backgroundLayer.draw();
// A layer for free drawing
let drawLayer = new Konva.Layer();
stage.add(drawLayer);
/* ---- Functions for mode change ----*/
function useHand () {
// Make stage draggable
stage.draggable(true);
// Make stage zoomable
// *** Code is copy and pasted from
// *** .html.html
let scaleBy = 1.3;
stage.on('wheel', (evt) => {
evt.evt.preventDefault();
let oldScale = stage.scaleX();
let mousePointTo = {
x: stage.getPointerPosition().x / oldScale - stage.x() / oldScale,
y: stage.getPointerPosition().y / oldScale - stage.y() / oldScale
};
let newScale = evt.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy;
stage.scale({ x: newScale, y: newScale });
let newPos = {
x: -(mousePointTo.x - stage.getPointerPosition().x / newScale) * newScale,
y: -(mousePointTo.y - stage.getPointerPosition().y / newScale) * newScale
};
stage.position(newPos);
stage.batchDraw();
});
}
function endHand () {
stage.draggable(false);
stage.off('wheel');
}
function usePen () {
let isDrawing = false;
let currentLine;
stage.on('mousedown', (evt) => {
// Start drawing
isDrawing = true;
// Create new line object
let pos = stage.getPointerPosition();
currentLine = new Konva.Line({
stroke: 'black',
strokeWidth: 3,
points: [pos.x, pos.y]
});
drawLayer.add(currentLine);
});
stage.on('mousemove', (evt) => {
if (!isDrawing) {
return;
}
// If drawing, add new point to the current line object
let pos = stage.getPointerPosition();
let newPoints = currentLine.points().concat([pos.x, pos.y]);
currentLine.points(newPoints);
drawLayer.batchDraw();
});
stage.on('mouseup', (evt) => {
// End drawing
isDrawing = false;
});
}
function endPen () {
stage.off('mousedown');
stage.off('mousemove');
stage.off('mouseup');
}
/* ---- Init ---- */
useHand();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Paper</title>
</head>
<body>
<select id="mode-selector">
<option value="Hand">Hand</option>
<option value="Pen">Pen</option>
</select>
<div id="container"></div>
<script src="/[email protected]/konva.min.js"></script>
<!-- <script src="konvaTest.js"></script> -->
<script src="buggyPaper.js"></script>
</body>
</html>
Any discussion is weled. Thanks for reading!
What I am trying to do
I'm trying to implement simple paper(whiteboard) using Konva.js.
So far I've implemented Drag, Zoom and Free drawing on paper.
I referred to
- https://konvajs/docs/sandbox/Zooming_Relative_To_Pointer.html for Zoom
- https://konvajs/docs/sandbox/Free_Drawing.html for Free drawing
I want to draw only on the region with beige color background, and I want to draw exactly under the pointer even though it is zoomed or dragged.
But Free drawing and both Drag and Zoom features don't work well together.
Bug
Can't draw correctly after dragging or zooming.
Where I think wrong thing is happening, but can't fix
I think something is wrong in the 2 parts bellow.
- Implementation of zoom
- How I use stage.getPointerPosition() in drawing implementation
- Or implementations of these two doesn't fit together
Code
Minimum code is here.
/* ---- Mode management ---- */
let modeSelector = document.getElementById('mode-selector');
let mode = modeSelector.value;
modeSelector.addEventListener('change', () => {
// Discaed event handlers used by old mode
switch (mode) {
case 'Hand': {
endHand();
break;
}
case 'Pen': {
endPen();
break;
}
}
// Set event handlers for new mode
mode = modeSelector.value;
switch (mode) {
case 'Hand': {
useHand();
break;
}
case 'Pen': {
usePen();
break;
}
}
});
/* ---- Konva Objects ---- */
let stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
// A layer that is only used for background color
let backgroundLayer = new Konva.Layer();
let backgroundColor = new Konva.Image({
width: window.innerWidth,
height: window.innerHeight,
fill: 'rgb(242,233,226)'
})
backgroundLayer.add(backgroundColor);
stage.add(backgroundLayer);
backgroundLayer.draw();
// A layer for free drawing
let drawLayer = new Konva.Layer();
stage.add(drawLayer);
/* ---- Functions for mode change ----*/
function useHand () {
// Make stage draggable
stage.draggable(true);
// Make stage zoomable
// *** Code is copy and pasted from
// *** https://konvajs/docs/sandbox/Zooming_Relative_To_Pointer.htmlhttps://konvajs/docs/sandbox/Zooming_Relative_To_Pointer.html
let scaleBy = 1.3;
stage.on('wheel', (evt) => {
evt.evt.preventDefault();
let oldScale = stage.scaleX();
let mousePointTo = {
x: stage.getPointerPosition().x / oldScale - stage.x() / oldScale,
y: stage.getPointerPosition().y / oldScale - stage.y() / oldScale
};
let newScale = evt.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy;
stage.scale({ x: newScale, y: newScale });
let newPos = {
x: -(mousePointTo.x - stage.getPointerPosition().x / newScale) * newScale,
y: -(mousePointTo.y - stage.getPointerPosition().y / newScale) * newScale
};
stage.position(newPos);
stage.batchDraw();
});
}
function endHand () {
stage.draggable(false);
stage.off('wheel');
}
function usePen () {
let isDrawing = false;
let currentLine;
stage.on('mousedown', (evt) => {
// Start drawing
isDrawing = true;
// Create new line object
let pos = stage.getPointerPosition();
currentLine = new Konva.Line({
stroke: 'black',
strokeWidth: 3,
points: [pos.x, pos.y]
});
drawLayer.add(currentLine);
});
stage.on('mousemove', (evt) => {
if (!isDrawing) {
return;
}
// If drawing, add new point to the current line object
let pos = stage.getPointerPosition();
let newPoints = currentLine.points().concat([pos.x, pos.y]);
currentLine.points(newPoints);
drawLayer.batchDraw();
});
stage.on('mouseup', (evt) => {
// End drawing
isDrawing = false;
});
}
function endPen () {
stage.off('mousedown');
stage.off('mousemove');
stage.off('mouseup');
}
/* ---- Init ---- */
useHand();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Paper</title>
</head>
<body>
<select id="mode-selector">
<option value="Hand">Hand</option>
<option value="Pen">Pen</option>
</select>
<div id="container"></div>
<script src="https://unpkg./[email protected]/konva.min.js"></script>
<!-- <script src="konvaTest.js"></script> -->
<script src="buggyPaper.js"></script>
</body>
</html>
Share
edited Mar 14, 2020 at 7:45
dynamicnoodle
asked Mar 14, 2020 at 5:45
dynamicnoodledynamicnoodle
511 silver badge4 bronze badges
1 Answer
Reset to default 8stage.getPointerPosition()
returns absolute position of pointer (related top-left corner of canvas container).
As you are transforming (moving and scaling a stage) you need to find a relative position, so you can use it for the line.
Relative mouse position demo demonstrates how to do that:
function getRelativePointerPosition(node) {
// the function will return pointer position relative to the passed node
var transform = node.getAbsoluteTransform().copy();
// to detect relative position we need to invert transform
transform.invert();
// get pointer (say mouse or touch) position
var pos = node.getStage().getPointerPosition();
// now we find a relative point
return transform.point(pos);
}
/* ---- Mode management ---- */
let modeSelector = document.getElementById('mode-selector');
let mode = modeSelector.value;
modeSelector.addEventListener('change', () => {
// Discaed event handlers used by old mode
switch (mode) {
case 'Hand': {
endHand();
break;
}
case 'Pen': {
endPen();
break;
}
}
// Set event handlers for new mode
mode = modeSelector.value;
switch (mode) {
case 'Hand': {
useHand();
break;
}
case 'Pen': {
usePen();
break;
}
}
});
/* ---- Konva Objects ---- */
let stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
// A layer that is only used for background color
let backgroundLayer = new Konva.Layer();
let backgroundColor = new Konva.Image({
width: window.innerWidth,
height: window.innerHeight,
fill: 'rgb(242,233,226)'
})
backgroundLayer.add(backgroundColor);
stage.add(backgroundLayer);
backgroundLayer.draw();
// A layer for free drawing
let drawLayer = new Konva.Layer();
stage.add(drawLayer);
/* ---- Functions for mode change ----*/
function useHand () {
// Make stage draggable
stage.draggable(true);
// Make stage zoomable
// *** Code is copy and pasted from
// *** https://konvajs/docs/sandbox/Zooming_Relative_To_Pointer.htmlhttps://konvajs/docs/sandbox/Zooming_Relative_To_Pointer.html
let scaleBy = 1.3;
stage.on('wheel', (evt) => {
evt.evt.preventDefault();
let oldScale = stage.scaleX();
let mousePointTo = {
x: stage.getPointerPosition().x / oldScale - stage.x() / oldScale,
y: stage.getPointerPosition().y / oldScale - stage.y() / oldScale
};
let newScale = evt.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy;
stage.scale({ x: newScale, y: newScale });
let newPos = {
x: -(mousePointTo.x - stage.getPointerPosition().x / newScale) * newScale,
y: -(mousePointTo.y - stage.getPointerPosition().y / newScale) * newScale
};
stage.position(newPos);
stage.batchDraw();
});
}
function endHand () {
stage.draggable(false);
stage.off('wheel');
}
function getRelativePointerPosition(node) {
// the function will return pointer position relative to the passed node
var transform = node.getAbsoluteTransform().copy();
// to detect relative position we need to invert transform
transform.invert();
// get pointer (say mouse or touch) position
var pos = node.getStage().getPointerPosition();
// now we find relative point
return transform.point(pos);
}
function usePen () {
let isDrawing = false;
let currentLine;
stage.on('mousedown', (evt) => {
// Start drawing
isDrawing = true;
// Create new line object
let pos = getRelativePointerPosition(stage);
currentLine = new Konva.Line({
stroke: 'black',
strokeWidth: 3,
points: [pos.x, pos.y]
});
drawLayer.add(currentLine);
});
stage.on('mousemove', (evt) => {
if (!isDrawing) {
return;
}
// If drawing, add new point to the current line object
let pos = getRelativePointerPosition(stage);
let newPoints = currentLine.points().concat([pos.x, pos.y]);
currentLine.points(newPoints);
drawLayer.batchDraw();
});
stage.on('mouseup', (evt) => {
// End drawing
isDrawing = false;
});
}
function endPen () {
stage.off('mousedown');
stage.off('mousemove');
stage.off('mouseup');
}
/* ---- Init ---- */
useHand();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Paper</title>
</head>
<body>
<select id="mode-selector">
<option value="Hand">Hand</option>
<option value="Pen">Pen</option>
</select>
<div id="container"></div>
<script src="https://unpkg./[email protected]/konva.min.js"></script>
<!-- <script src="konvaTest.js"></script> -->
<script src="buggyPaper.js"></script>
</body>
</html>
本文标签:
版权声明:本文标题:javascript - Konva.js: [Free drawing & Drag & Zoom] Can't draw correctly with pointer after Drag or Zoom 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742143550a2422688.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论