Recently I have been working with responsive design and I decided I would make a page with some quotes and a place where you can then sign your name. The place where you can sign uses mouse and touch events to draw on canvas. It works perfectly with a mouse but with touch when I try to drag and draw it just highlights box but I can draw one dot at a time by tapping but I want it to drag normally like with the mouse. I have set default off for things however I still cannot fix this issue. I don't know if it has something to do with the canvas being highlighted with touch. Here is the individual code for the touch not in my site but in a canvas webpage by itself:
<html>
<head>
<title>Sketchpad</title>
<script type="text/javascript">
var canvas;
var ctx;
var mouseX;
var mouseY;
var mouseDown=0;
var touchX,touchY;
function drawCircle(ctx,x,y,size) {
r=0; g=0; b=0; a=255;//opaque
ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
function clearCanvas(canvas,ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
//get mouse position
function getMousePosition(moves) {
if (!moves)
var moves = event;
if (moves.offsetX) {
mouseX = moves.offsetX;
mouseY = moves.offsetY;
}
else if (moves.layerX) {
mouseX = moves.layerX;
mouseY = moves.layerY;
}
}
function canvases_touchStart() {
getTouchPosition();
drawCircle(ctx,touchX,touchY,4);
//prevents another mousedown
event.preventDefault();
}
//draw and prevent default scrolling with touch
function canvase_touchMove(moves) {
getTouchPosition(moves);
drawCircle(ctx,touchX,touchY,4);
//prevent scrolling
event.preventDefault();
}
function getTouchPosition(moves) {
if (!moves)
var moves = event;
if(moves.touches) {
if (moves.touches.length == 1) { //one finger
var touch = moves.touches[0]; //get info for finger
touchX=touch.pageX-touch.target.offsetLeft;
touchY=touch.pageY-touch.target.offsetTop;
}
}
}
function canvase_mouseDown() {
mouseDown=1;
drawCircle(ctx,mouseX,mouseY,4);
}
function canvase_mouseUp() {
mouseDown=0;
}
function canvase_mouseMove(moves) {
getMousePosition(moves);
if (mouseDown==1) {
drawCircle(ctx,mouseX,mouseY,4);
}
}
function init() {
canvas = document.getElementById('canvase');
if (canvas.getContext)
ctx = canvas.getContext('2d');
//check for ctx first
if (ctx) {
canvas.addEventListener('mousedown', canvase_mouseDown, false);
canvas.addEventListener('mousemove', canvase_mouseMove, false);
window.addEventListener('mouseup', canvase_mouseUp, false);
canvas.addEventListener('touchstart', canvase_touchStart, false);
canvas.addEventListener('touchmove', canvase_touchMove, false);
}
}
</script>
<style>
#whole {
/*prevents highlighting text*/
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#instructions {
width:30%;
height:15%;
padding:2px;
border-radius:4px;
font-size:120%;
display: block;
margin-left: auto;
margin-right: auto;
text-align:center;
}
#board {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1%;
}
#canvase {
height:300;
width:400;
border:2px solid black;
border-radius:4px;
position:relative;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1%;
}
#clearbutton {
font-size: 150%;
padding: 2px;
-webkit-appearance: none;
background: green;
border: 1px solid black;
color:white;
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body onload="init()">
<div id="whole">
<div id="instructions">
Sign name by tapping or dragging in box (draw slowly to prevent single <br/><br/>
<input type="submit" value="Clear Board" id="clearbutton" onclick="clearCanvas(canvas,ctx);">
</div>
<div id="board">
<canvas id="canvase" height="300" width="400">
</canvas>
</div>
</div>
</body>
</html>
Does anyone have any thoughts on this issue or a way to fix it?
Seems like the canvase_touchStart event is causing the issue.
You may remove the line canvas.addEventListener('touchstart', canvase_touchStart, false); and the corresponding function function canvases_touchStart() {...}
CODEPEN
Hope this helps.
PS: To know how to create a smoother effect, you may refer to this CODEPEN as well.
Related
I'm given to understand that the <frameset> tag is deprecated as of HTML5. Thankfully, Chrome still supports rendering it, and unfortunately, it's currently the only thing I've found that fits my use case.
The important element of the <frameset> tag that other frame-like objects lack is draggable borders, which I haven't been able to get working with iframes even with a prohibitive amount of javascript assistance.
The other important thing in my case is that one of the frames contains a button/link that causes the other frame to disappear or reappear. When that happens, the frames should resize appropriately to fill the space.
My current HTML looks like the following MCVE:
index.html
<html>
<head>
<script language="javascript">
function toggleBottomFrame() {
var bottomFrame = document.getElementById("bottomFrame");
var horizFrameset = document.getElementById("horizFrameset");
if (bottomFrame.style.display == "none") {
bottomFrame.style.display = "";
horizFrameset.rows = "*,25%";
} else {
bottomFrame.style.display = "none";
horizFrameset.rows = "*,0px";
}
}
document.toggleBottomFrame = toggleBottomFrame;
</script>
</head>
<frameset id="horizFrameset" rows="*,0px">
<frameset id="vertFrameset" cols="300px,*">
<frame id="topLeftFrame" src="buttonpage.html"></frame>
<frame id="topRightFrame"></frame>
</frameset>
<frame id="bottomFrame" style="display:none"></frame>
</frameset>
</html>
buttonpage.html
<html>
<head></head>
<body>
<button onclick="parent.frameElement.ownerDocument.toggleBottomFrame();">
</body>
</html>
This works both in the IE11 that the code was initially written for (and needs to continue to support), as well as in Chrome.
How do I implement the exact same functionality (including, most importantly, the ability to drag around the borders of the frames with my mouse to expand or shrink one of the frames) using non-deprecated functionality?
If possible, I'd like a solution in standard client-side JS or HTML, without needing to import another library like resize.js. This is meant for a very lightweight frontend, and I don't want to bloat it down with libraries I don't need.
You should be able to achieve the shrink and grown functionality using the flex layout. Below 2 approaches may work. Both the approaches has the right section and bottom section as iframe and the left section has button to show and hide the right and bottom sections.
Option 1
Using flex and using the css resize property.
Drawback is that you will need to resize using the resize button shown at the bottom right corners. The left section's bottom right corner can be used for horizontal resizing and the right section's bottom right corner can be used for vertical resizing. Note that due to the iframe contents the right section's bottom right corner resize button may not be visible, but if you bring the cursor to the bottom right you will see the cursor changing to resize and allowing you to resize.
function toggleBottom() {
if (document.getElementById('bottomFrame').clientHeight > 0) {
document.getElementById('topFrame').style.height = '100%';
} else {
document.getElementById('topFrame').style.height = '80%';
}
}
function toggleRight() {
if (document.getElementById('topRightFrame').clientWidth > 0) {
document.getElementById('topLeftFrame').style.width = '100%';
} else {
document.getElementById('topLeftFrame').style.width = '50%';
}
}
html,
body {
height: 98%;
}
.page-container {
display: flex;
flex-direction: column;
}
.container {
display: flex;
flex-direction: row;
resize: vertical;
border: 1px solid #000;
overflow: hidden;
}
.container-top {
height: 80%;
}
.container-bottom {
flex: 1 1;
overflow: hidden;
}
.container-left {
width: 30%;
border: 1px solid #000;
resize: horizontal;
overflow: hidden;
}
.container-right {
flex: 1 1;
height: 100%;
border: 1px solid #000;
overflow: hidden;
display: flex;
}
.frame-right {
flex: 1 1;
}
.frame-bottom {
flex: 1 1 100%;
border: 1px solid #000;
}
<html>
<body class="page-container">
<div class="container container-top" id="topFrame">
<div class="container-left" id="topLeftFrame">
<button onclick="toggleBottom()">Toggle Bottom</button>
<button onclick="toggleRight()">Toggle Right</button>
</div>
<div class="container-right" id="topRightFrame" >
<iframe src="https://stackoverflow.com" class="frame-right">
</iframe>
</div>
</div>
<div class="container container-bottom" id="bottomFrame">
<iframe class="frame-bottom" src="https://stackoverflow.com"></iframe>
</div>
</body>
</html>
Option 2
Using flex and using some scripting we should be able to make the whole border draggable. This is inspired from the answer in https://stackoverflow.com/a/53220241/2772300
const topRightFrame = document.getElementById("topRightFrame");
const topLeftFrame = document.getElementById("topLeftFrame");
const bottomFrame = document.getElementById("bottomFrame");
const topFrame = document.getElementById("topFrame");
const borderSize = 4;
function toggleBottom() {
if (bottomFrame.clientHeight > borderSize) {
topFrame.style.height = '100%';
} else {
topFrame.style.height = '80%';
}
}
function toggleRight() {
if (topRightFrame.clientWidth > borderSize) {
topLeftFrame.style.width = '100%';
} else {
topLeftFrame.style.width = '50%';
}
}
let mousePosition;
function resizeHorizontal(e){
const dx = mousePosition - e.x;
mousePosition = e.x;
topLeftFrame.style.width = (parseInt(getComputedStyle(topLeftFrame, '').width) - dx) + "px";
}
topRightFrame.addEventListener("mousedown", function(e){
if (e.offsetX < borderSize) {
mousePosition = e.x;
document.addEventListener("mousemove", resizeHorizontal, false);
}
}, false);
document.addEventListener("mouseup", function(){
document.removeEventListener("mousemove", resizeHorizontal, false);
}, false);
function resizeVertical(e){
const dy = mousePosition - e.y;
mousePosition = e.y;
topFrame.style.height = (parseInt(getComputedStyle(topFrame, '').height) - dy) + "px";
}
bottomFrame.addEventListener("mousedown", function(e){
if (e.offsetY < borderSize) {
mousePosition = e.y;
document.addEventListener("mousemove", resizeVertical, false);
}
}, false);
document.addEventListener("mouseup", function(){
document.removeEventListener("mousemove", resizeVertical, false);
}, false);
html,
body {
height: 98%;
}
.page-container {
display: flex;
flex-direction: column;
}
.container {
display: flex;
flex-direction: row;
overflow: hidden;
}
.container-top {
height: 80%;
}
.container-left {
width: 50%;
overflow: hidden;
height: 100%;
}
.container-right {
flex: 1 1;
height: 100%;
overflow: hidden;
display: flex;
padding-left: 4px;
background-color: #ccc;
cursor: ew-resize;
}
.frame-right {
flex: 1 1;
}
.container-bottom {
flex: 1 1;
overflow: hidden;
padding-top: 4px;
background-color: #ccc;
cursor: ns-resize;
}
.frame-bottom {
flex: 1 1 100%;
}
iframe {
border: 0;
}
<html>
<body class="page-container">
<div class="container container-top" id="topFrame">
<div class="container-left" id="topLeftFrame">
<button onclick="toggleBottom()">Toggle Bottom</button>
<button onclick="toggleRight()">Toggle Right</button>
</div>
<div class="container-right" id="topRightFrame" >
<iframe src="https://stackoverflow.com" class="frame-right">
</iframe>
</div>
</div>
<div class="container container-bottom" id="bottomFrame">
<iframe class="frame-bottom" src="https://stackoverflow.com"></iframe>
</div>
</body>
</html>
Have you looked a Golden Layout to do the resizing? You could then place iframes inside to match the size of the containing div.
Sorry this not a more complete answer, but though this might be an area worth exploring that is not likely to come up.
I've built a slider using pure JavaScript. On mobile screen when I touch the slider I can only change slides but can not scroll down the page.
Under the hood when the slider element is touched, a "touchstart" event fires and the corresponding event handler function, features event.preventDefault() to stop scrolling the page, then when "touchmove" event fires, the code uses difference between first and new horizontal coordinates and CSS left propery to move the slider.
I made a minimal code below. Also click to see code on online editor.
const slides = document.querySelector(".slides");
let posX1, posX2, dX;
slides.addEventListener("touchstart", dragStart);
slides.addEventListener("touchmove", dragAction);
function dragStart(e) {
e.preventDefault();
posX1 = e.touches[0].clientX;
}
function dragAction(e) {
posX2 = e.touches[0].clientX;
dX = posX2 - posX1;
posX1 = e.touches[0].clientX;
slides.style.left = (slides.offsetLeft + dX) + "px";
}
body {
padding-bottom: 1000px;
}
.slider {
width: 200px;
height: 100px;
margin: 0 auto;
border: 1px solid black;
position: relative;
overflow: hidden;
}
.slides {
width: 600px;
height: 100px;
display: flex;
position: absolute;
}
.slide {
width: 200px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.slide:nth-child(1) {
background-color: rgb(200, 200, 200);
}
.slide:nth-child(2) {
background-color: rgb(150, 150, 150);
}
.slide:nth-child(3) {
background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>
<body>
<div class="slider">
<div class="slides">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
</div>
</div>
</body>
</html>
Thanks for your time :)
I think nobody has checked my question but me, however, assuming there's a hypothetical person having the same problem as mine, I could fix that:
I figured out how to make a JavaScript slider using this post in which the author has used preventDefault() inside "touchstart" EventListener and I stuck to it, but the solution is to simply call preventDefault() method on "touchmove" event itself not "touchstart", off course if you need (which is if the user's trying to change slides). and if user's trying to scroll the page then remove "touchend" EventListener.
const slides = document.querySelector(".slides");
let posX1,
posX2,
posY1,
posY2,
dX,
dY,
dirDetected = false;
//feature detection
//-------------Note 1-----------//
let passiveIfSupported = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, "passive", {
get: function() {passiveIfSupported = {passive: false};}
}));
} catch(err) {}
slides.addEventListener("touchstart", dragStart, passiveIfSupported);
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
slides.addEventListener("touchend", dragEnd, false);
function dragStart(e) {
posX1 = e.touches[0].clientX;
posY1 = e.touches[0].clientY;
}
function dragAction(e) {
//-------------Note 2-----------//
e.preventDefault();
posX2 = e.touches[0].clientX;
posY2 = e.touches[0].clientY;
dX = posX2 - posX1;
posX1 = e.touches[0].clientX;
dY = posY2 - posY1;
if (!dirDetected) {
if (Math.abs(dY) > Math.abs(dX)) {
slides.removeEventListener("touchmove", dragAction, passiveIfSupported);
return;
}
dirDetected = true;
}
slides.style.left = (slides.offsetLeft + dX) + "px";
}
function dragEnd() {
if (!dirDetected) {
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
}
dirDetected = false;
}
body {
padding-bottom: 1000px;
}
.slider {
width: 200px;
height: 100px;
margin: 0 auto;
border: 1px solid black;
position: relative;
overflow: hidden;
}
.slides {
width: 600px;
height: 100px;
display: flex;
position: absolute;
}
.slide {
width: 200px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.slide:nth-child(1) {
background-color: rgb(200, 200, 200);
}
.slide:nth-child(2) {
background-color: rgb(150, 150, 150);
}
.slide:nth-child(3) {
background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>
<body>
<div class="slider">
<div class="slides">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
</div>
</div>
</body>
</html>
Note 1. (addEventListener's third parameter): note the third parameter of addEventListener() method. there's something I realized in my searches from this question. I'm going to use preventDefault() inside "touchmove" EventListener but in some versions of Chrome and Firefox for "touchstart" and "touchmove" events if you don't specify passive property of options object (the third parameter of addEventListener()) the default value would be set to true and this doesn't let the EventListener to call preventDefault() so you have to set the third parameter to {passive: false} but if the browser loading your script is an old one which requires a third boolean parameter for addEventListener() then you need to provide a boolean value not object. So you can use feature detection to provide an appropraite parameter.
Note 2. Firefox and chrom android handle "touchmove" preventDefault() differently: Here's another point I found (from this question), if you run the above code on Chrome Android it works well, you can scroll the page or change slides but on Firefox Android you can't scroll. Actually I think it's a Chrome's fault because according to Specs for "touchmove" event if the first "touchmove" event is prevented the subsequent "touchmove" events bound to the same touch point are prevented and in the code above at the very first line of "touchmove" event handler function I used preventDefault() so I need to call it after the if block so ensure default behaviour is prevented when needed.
const slides = document.querySelector(".slides");
let posX1,
posX2,
posY1,
posY2,
dX,
dY,
dirDetected = false;
//feature detection
let passiveIfSupported = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, "passive", {
get: function() {passiveIfSupported = {passive: false};}
}));
} catch(err) {}
slides.addEventListener("touchstart", dragStart, passiveIfSupported);
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
slides.addEventListener("touchend", dragEnd, false);
function dragStart(e) {
posX1 = e.touches[0].clientX;
posY1 = e.touches[0].clientY;
}
function dragAction(e) {
posX2 = e.touches[0].clientX;
posY2 = e.touches[0].clientY;
dX = posX2 - posX1;
posX1 = e.touches[0].clientX;
dY = posY2 - posY1;
if (!dirDetected) {
if (Math.abs(dY) > Math.abs(dX)) {
slides.removeEventListener("touchmove", dragAction, passiveIfSupported);
return;
}
e.preventDefault();
}
dirDetected = true;
slides.style.left = (slides.offsetLeft + dX) + "px";
}
function dragEnd() {
if (!dirDetected) {
slides.addEventListener("touchmove", dragAction, passiveIfSupported);
}
dirDetected = false;
}
body {
padding-bottom: 1000px;
}
.slider {
width: 200px;
height: 100px;
margin: 0 auto;
border: 1px solid black;
position: relative;
overflow: hidden;
}
.slides {
width: 600px;
height: 100px;
display: flex;
position: absolute;
}
.slide {
width: 200px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.slide:nth-child(1) {
background-color: rgb(200, 200, 200);
}
.slide:nth-child(2) {
background-color: rgb(150, 150, 150);
}
.slide:nth-child(3) {
background-color: rgb(100, 100, 100);
}
<!DOCTYPE html>
<html>
<body>
<div class="slider">
<div class="slides">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
</div>
</div>
</body>
</html>
I'm creating an interactive art piece, which people can collaborate on. What I want is that there is a library of icons people can use. And when clicking on them, the mouse gets a class and thus when clicking on a specific cell in the table, the cell will get the icon as their background image.
(Now I know I will need a database etc, but that's for later. First things first.)
I did something similar a long time ago, but I don't know how to edit this in order to work for this project:
function nextPic() {
if ( $('html,body').css('cursor').indexOf('cursor2.png') > 0 )
{
counter += 1;
if (counter > myPictures.length - 1) {
// counter = 0;
}
else {
element.style.backgroundImage = "url(" + myPictures[counter] + ")";
}
}
It just works according to the image on the cursor. Not ideal at all, it bugged ALL the time.
I've looked at a code for pixel art, which (kind of) does what needs t one done. But not quite.
The pixel art fiddle here:
https://jsfiddle.net/bxstmufj/
So here is an example of someone doing what you want but instead of in a table grid in a canvas. Mad props to them for putting this out:
http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/
After the basic drawing on a canvas they add the ability to pick colors. Notice how they save the picked color into a variable that is then called on for the canvas reDraw() function.
The same thing can be done with icons. Simply having an onClick event for whatever icon is clicked just like they did with colors (in their case they chose mousedown event):
$('#choosePurpleSimpleColors').mousedown(function(e){
curColor_simpleColors = colorPurple;
});
That is the event handler they put on the purple button for example. You can see this by inspecting the element (button) then on the right click Event Handlers then go to the mousedown event and then you can click on the javascript file location where this code is. (All of this done in chrome inspect{right click, then pick inspect})
Now if you did not want to do it on a canvas but instead a a table/grid all you would do is set onClick events for the cells. They would then call on the color/icon variable and set them for that cell.
Let me know if you would like an example for a grid/table. The canvas is a bit more of a complex answer but I suspect it is what you really prefer. The second example and beyond is really what you want so you could also pick icons to insert.
context = document.getElementById('canvas').getContext("2d");
$('#canvas').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#canvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#canvas').mouseup(function(e){
paint = false;
});
$('#canvas').mouseleave(function(e){
paint = false;
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function redraw(){
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" width="490" height="220" style="border: solid 1px black;"></canvas>
Fixed!
<div id="p1" class="pen"></div>
<div id="p2" class="pen"></div>
<div id="art">
<div class="row">
<div class="pixel"></div>
<div class="pixel"></div>
</div>
</div>
icon = '(icon.png)'
$('#p1').click(function (){
icon = "icon2.png";
alert(icon);
});
$('#p2').click(function (){
icon = "icon3.png";
alert(icon);
});
// onclick function classes
$(".pixel").click(function() {
//function that changes background to url
// $(this).css('background-image', var(icon));
// $(this).css("background-image", "url(" + icon")");
$(this).css("background-image", "url(" +icon +")");
});
#art {
display: table;
border-spacing: 1px;
background-color: black;
border: 1px solid black;
}
.row {
display: table-row;
}
.pixel {
display: table-cell;
background-color: white;
width: 25px;
margin: 1px;
height: 25px;
background-size: contain;
}
.pen {
display: inline-block;
width: 40px;
height: 40px;
border: 2px solid black;
}
I don't know about using a class to set varied colors; a class would infer that they are all the same. You'd have to use ids to differentiate. You could pass the id and the color that you want to change the background to to a function and work it that way. Or you might opt to put the colors in an array and use the index number?
I made a basic example using the squares in your fiddle, to give an idea. As you can see, I only assigned one of the two a background value using css. The function can be tweaked to change background image if you want to use images instead of colors of course..
Hope this helps
function setPenColour(id, pixel) {
var myDiv = document.getElementById(id);
myDiv.style.backgroundColor = pixel;
}
#p1 {
background-color: grey;
}
#art {
display: table;
border-spacing: 1px;
background-color: black;
border: 1px solid black;
}
.row {
display: table-row;
}
.pixel {
display: table-cell;
background-color: white;
width: 25px;
margin: 1px;
height: 25px;
}
.pen {
display: inline-block;
width: 40px;
height: 40px;
border: 2px solid black;
}
<div id="p1" class="pen" onclick="setPenColour(id, '#00FF00')" ;></div>
<div id="p2" class="pen" style="background-color:blue;" onclick="setPenColour(id, 'red')"></div>
How to remove ghost image when drag the image. We have tried code, its working in Firefox and chrome but not working in Safari. Please any one help what is the mistake of my code.
https://jsfiddle.net/rajamsr/Lfuq5qb6/
document.addEventListener("dragstart", function( event ) {
dragged = event.target;
event.dataTransfer.setDragImage(dragged, 11111110, 10);
}, false);
You can prevent showing the ghost preview by showing empty/transparent image:
document.addEventListener("dragstart", function( event ) {
var img = new Image();
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=';
event.dataTransfer.setDragImage(img, 0, 0);
}, false);
Do not use the event.target as an argument to setDragImage, this is probably causing the memory issues here.
You can always add a custom image, the image could as well be a transparent PNG.
Here is an example how that goes.
var dragMe = document.getElementById("drag-me"),
img = new Image();
img.onload = function () {
dragMe.addEventListener("dragstart", function(e) {
e.dataTransfer.setDragImage(img, 0, 0);
}, false);
}
img.src = "http://placehold.it/150/000000/ffffff?text=GHOST";
#drag-me {
width: 100px;
height: 100px;
background-color: black;
line-height: 100px;
text-align: center;
}
#drag-me > img {
vertical-align: middle;
}
<div id="drag-me">
<img src="https://jsfiddle.net/img/logo.png" draggable="true" />
</div>
Another option would be to just clone the node element and set its visibility to hidden. But for this option to work it is necessary to add the cloned element to the DOM.
An example with the cloned node could look like this. I am not hiding the node completely, so you can see what is happening.
var dragMe = document.getElementById("drag-me");
dragMe.addEventListener("dragstart", function(e) {
var clone = this.cloneNode(true);
clone.style.opacity = 0.1; // use opacity or
//clone.style.visibility = "hidden"; // visibility or
//clone.style.display = "none"; // display rule
document.body.appendChild(clone);
e.dataTransfer.setDragImage(clone, 0, 0);
}, false);
#drag-me {
width: 100px;
height: 100px;
background-color: black;
line-height: 100px;
text-align: center;
}
#drag-me > img {
vertical-align: middle;
}
<div id="drag-me">
<img src="https://jsfiddle.net/img/logo.png" draggable="true" />
</div>
You could just use the event.target and position it using the window's outerWidth and outerHeight
document.addEventListener("dragstart", function( event ) {
event.dataTransfer.setDragImage(event.target, window.outerWidth, window.outerHeight);
}, false);
Your code is causing memory issues.
Instead use css to stop user-drag/select, this works in most browsers but there is a bug it seems in firefox that it doesn't work so add ondragstart="return false;" to img tags to fix this see https://jsfiddle.net/Lfuq5qb6/1/
<img class="normal-logo hidden-xs" src="..." alt="logo" ondragstart="return false;"/>
img{
user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-ms-user-select: none;
}
function removeGhosting(event) {
if(!(event instanceof MouseEvent)) {
console.info("Parameters must be of type MouseEvent!")
return;
}
let dragIcon = document.createElement('img');
dragIcon.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
dragIcon.width = 0;
dragIcon.height = 0;
dragIcon.opacity = 0;
if(event.dataTransfer) {
event.dataTransfer.setDragImage(dragIcon,0, 0);
}
}
enter link description here
You can set img draggable attribute to false.
<img id="" src="..." draggable="false">
And to disable selection on images, you can use
<style>
img{
user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
I am new to JavaScript/CSS (basically the whole world of web dev) and I am really struggling to create the following widget. I created a picture of what I want to make to make it more clear.
The Play/Pause and Stop button are ready. Loop checkbox is no problem. But the progress bar is painful. The two markers are supposed to mark the point from where the file would start playing and where it would stop. The progress bar is also supposed to be click-able, so if I want to access a certain point in time, then its possible.
What I tried so far
jQuery UI slider: For a sliding progress bar and use that draggable slider to access a certain point in audio file. Works fine. But no markers and looks really ugly. Don't how to change it.
<progress> tag: not very flexible. Marker? Clicking?
<div> tag: there seems to be no way to get the point where I clicked.
So, what do you guys recommend? How should I proceed?
Canvas Alternative
You might want to use a canvas and draw your own progress bar element within it.
Here are some canvas progress bar tutorials:
How to create a progress bar with HTML5
A progress bar using HTML5 canvas
Doing it with <progress>
To access the clicked position within a DOMElement, you can proceed with the click event's properties: clientX and clientY (MDN Source), like so:
HTML
<div class="marker" id="StartMarker">^</div>
<div class="marker" id="StopMarker">^</div>
<progress id="progress" value="0" min="0" max="100">0%</progress>
<form id="choice">
<button id="marker1">Beginning marker</button>
<button id="marker2">Ending marker</button>
<input type="hidden" id="markerValue" value="0" />
</form>
JavaScript (not optimized)
document.getElementById('progress').onclick = function (event, element) {
/* Math.floor((event.offsetX / this.offsetWidth) * 100) */
var newProgress = event.offsetX;
document.getElementById('choice').style.display = "block";
document.getElementById('markerValue').setAttribute('value', newProgress);
document.getElementById('marker1').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
var marker = startMarker;
marker.style.display = "block";
startMarker.style.display = "block";
startMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
startMarker.style.left = newProgress + "px";
};
document.getElementById('marker2').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
stopMarker.style.display = "block";
stopMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
stopMarker.style.left = newProgress + "px";
};
};
CSS
.marker {
position:absolute;
top:24px;
left:9px;
display:none;
z-index:8;
font-weight:bold;
text-align:center;
}
#StartMarker {
color: #CF0;
}
#StopMarker {
color:#F00;
}
#choice {
display:none;
}
progress {
display: inline-block;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 300px;
height: 20px;
padding: 3px 3px 2px 3px;
background: #333;
background: -webkit-linear-gradient(#2d2d2d, #444);
background: -moz-linear-gradient(#2d2d2d, #444);
background: -o-linear-gradient(#2d2d2d, #444);
background: linear-gradient(#2d2d2d, #444);
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 15px;
box-shadow: 0 1px 0 rgba(255, 255, 255, .2);
}
Live Demo
Using simple blocks for that is possible. Your layout would look like this (simplified):
HTML
<div class="progressbar">
<div class="bar">
<div class="progress" style="width: 30%;">
</div>
</div>
<div class="markers">
<div class="right" style="width: 70%;">
<div class="marker">
</div>
<div class="left" style="width: 20%;">
<div class="marker">
</div>
</div>
</div>
</div>
</div>
SCSS
.progressbar {
width: 20em;
background: grey;
.bar {
height: 2em;
.progress {
background: blue;
height: 100%;
}
}
.markers {
height: 1em;
background: white;
.right {
height: 100%;
background: red;
.marker {
width: 1em;
height: 100%;
background: green;
position: relative;
float: right;
}
.left {
background: white;
height: 100%;
}
}
}
}
The operations can be quite difficult
jQuery
$('.bar').click(function(e){
$(this).find('.progress').css('width', (e.offsetX / this.offsetWidth)*100+'%');
});
will set the Progressbar properly on clicks.
For the markers though you will need mousedown, mousemove, mouseleave events, since you got 2 of them.
Example
http://jsfiddle.net/JXauW/