I want to save and restore data from div - that is container of other divs,
In order to make it I use local storage and JSON like this:
window.onload = restoreJason;
function makeJson(){
var canvas = document.getElementById("canvas");
var shapes = canvas.querySelectorAll("div[class='drag']");
var divs = new Object();
for(var i=0; i<shapes.length; ++i){
divs[shapes[i].getAttribute('innerHTML')] = shapes[i].innerHTML;
}
localStorage.setItem("divs", JSON.stringify(divs));
}
function restoreJason(){
var divs = JSON.parse(localStorage.getItem("divs"));
var canvas = document.getElementById("canvas");
var shapes = canvas.querySelectorAll("div[class='drag']");
for(var i = 0; i<shapes.length; i++){
shapes[i].value = divs[shapes[i].getAttribute("innerHTML")];
}
console.log(divs);
}
However, I don't know how to access the innerHTML of the elements and save it or restore it.
What do you think I shall do?
(To be more detailed - I need to save the content of the div when user click on "save", and load it when the user click "load". This is a snippest of it...)
NOTICE: the "canvas" is just the id of the main div, and not a real "canvas".
function randomizeColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * letters.length)];
}
return color;
}
function randomizeRectangle() {
var width = Math.random() * 700 + 50;
var height = Math.random() * 250 + 50;
if (height <= 20) {
height = 20;
}
var posX = Math.round(Math.random() * window.innerWidth);
var posY = Math.round(Math.random() * window.innerHeight);
var randomRecObj = {
"width": width + "px",
"height": height + "px",
"posX": posX,
"posY": posY
};
return randomRecObj;
}
function makeShape() {
var rect = randomizeRectangle();
var rectDOM = document.createElement("div");
rectDOM.className = "rectangle";
rectDOM.style.border = "1px solid black";
rectDOM.style.width = rect.width;
rectDOM.style.height = rect.height;
rectDOM.style.background = randomizeColor();
rectDOM.style.top = rect.posY + "px";
rectDOM.style.left = rect.posX + "px";
//rectDOM.addEventListener("click", selectShape);
// rectDOM.style.transform =rect.rotation;
return rectDOM;
}
function randRect() {
var rectDOM = makeShape();
var canvas = document.getElementById("canvas");
canvas.appendChild(rectDOM);
}
function randOval() {
var ovalDOM = makeShape();
ovalDOM.style.borderRadius = "50%";
var canvas = document.getElementById("canvas");
canvas.appendChild(ovalDOM);
}
function changeColor(){
}
function cancelSelection() {
var selected = document.getElementsByClassName("selected");
while (selected) {
selected[0].classList.remove(selected[0]);
}
}
function removeShape(event) {
var selectedShapes = document.getElementsByClassName("selected");
var len = selectedShapes.length;
while (len > 0) {
selectedShapes[0].parentNode.removeChild(selectedShapes[0]);
--len;
}
}
function removeCorners(rectDom) {
var corners = document.getElementsByClassName("corners");
var len = corners.length;
while (len > 0) {
corners[0].classList.remove("corners");
--len;
}
}
.header{
background: #4ABDAC;
color: #fff;
margin: 1px;
}
hr{
border-top: 3px double #2a3132;
}
ul{
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #90afc5;
}
li{
float: left;
border: 2px solid #336b87;
padding: 3px;
margin: 3px;
}
li>a{
display: block;
color: #2a3132;
text-decoration: none;
padding: 10px 14px;
}
#color{
margin-left: 150px;
}
#rect{
margin-left: 100px;
}
li>a:hover{
color: #763626;
cursor: pointer;
}
#canvas{
background: #66a5ad;
position: relative;
height: 1200px;
width: 100%;
}
.corners{
position: absolute;
height: 10px;
width: 10px;
background:#fff;
border: 1px solid black;
display: none;
}
.selected .corners{
display: inline-block;
}
.cornerUpLeft{
top: -5px;
left: -5px;
}
.cornerUpRight{
top: -5px;
right: -5px;
}
.cornerBtmLeft{
bottom: -5px;
left: -5px;
}
.cornerBtmRight{
bottom: -5px;
right: -5px;
}
.rectangle{
position: absolute;
}
.colorBox{
border: 1px solid black;
height: 20px;
width: 20px;
list-style: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sketch Board - Eyal Segal Project</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/style.css" rel="stylesheet">
<script src="js/sketch.js"></script>
</head>
<body>
<h1 class="header">Sketch Board</h1>
<div>
<ul class="toolbar">
<li><a>Load</a></li>
<li id="Save"><a>Save</a></li>
<li id="rect"><a onclick="randRect()">Rectangle</a></li>
<li><a onclick="randOval()">Oval</a></li>
</ul>
<hr>
</div>
<div class="canvas" id="canvas">
</div>
</body>
</html>
All you need to do is set the .innerHTML of the div id="canvas" into localStorage. There's no need for JSON or loops at all.
Also, don't use inline HTML event attributes (onclick). Instead, do all your JavaScript separately using modern, standards based event handling.
Lastly, there is no need for <a> elements to be able to respond to a click event. Actually, your a elements are invalid as they don't have a name or href attribute anyway. The li elements can simply be set up for click events.
This is the code to do it but it won't execute here in the Stack Overflow snippet environment, but you can see it working here.
// Get reference to the "canvas"
var can = document.getElementById("canvas");
// Save the content of the canvas to localStorage
function saveData(){
localStorage.setItem("canvas", can.innerHTML);
}
// Get localStorage data
function restoreData(){
can.innerHTML = localStorage.getItem("canvas");
}
// get load and save references
var load = document.getElementById("load");
var save = document.getElementById("save");
// Set up event handlers
load.addEventListener("click", restoreData);
save.addEventListener("click", saveData);
// Get references to the rect and oval "buttons" and set their event handlers
var rect = document.getElementById("rect");
rect.addEventListener("click", randRect);
var oval = document.getElementById("oval");
oval.addEventListener("click", randOval);
function randomizeColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * letters.length)];
}
return color;
}
function randomizeRectangle() {
var width = Math.random() * 700 + 50;
var height = Math.random() * 250 + 50;
if (height <= 20) {
height = 20;
}
var posX = Math.round(Math.random() * window.innerWidth);
var posY = Math.round(Math.random() * window.innerHeight);
var randomRecObj = {
"width": width + "px",
"height": height + "px",
"posX": posX,
"posY": posY
};
return randomRecObj;
}
function makeShape() {
var rect = randomizeRectangle();
var rectDOM = document.createElement("div");
rectDOM.className = "rectangle";
rectDOM.style.border = "1px solid black";
rectDOM.style.width = rect.width;
rectDOM.style.height = rect.height;
rectDOM.style.background = randomizeColor();
rectDOM.style.top = rect.posY + "px";
rectDOM.style.left = rect.posX + "px";
//rectDOM.addEventListener("click", selectShape);
// rectDOM.style.transform =rect.rotation;
return rectDOM;
}
function randRect() {
var rectDOM = makeShape();
var canvas = document.getElementById("canvas");
canvas.appendChild(rectDOM);
}
function randOval() {
var ovalDOM = makeShape();
ovalDOM.style.borderRadius = "50%";
var canvas = document.getElementById("canvas");
canvas.appendChild(ovalDOM);
}
function changeColor(){
}
function cancelSelection() {
var selected = document.getElementsByClassName("selected");
while (selected) {
selected[0].classList.remove(selected[0]);
}
}
function removeShape(event) {
var selectedShapes = document.getElementsByClassName("selected");
var len = selectedShapes.length;
while (len > 0) {
selectedShapes[0].parentNode.removeChild(selectedShapes[0]);
--len;
}
}
function removeCorners(rectDom) {
var corners = document.getElementsByClassName("corners");
var len = corners.length;
while (len > 0) {
corners[0].classList.remove("corners");
--len;
}
}
.header{
background: #4ABDAC;
color: #fff;
margin: 1px;
}
hr{
border-top: 3px double #2a3132;
}
ul{
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #90afc5;
}
li{
float: left;
border: 2px solid #336b87;
padding: 3px;
margin: 3px;
}
li>a{
display: block;
color: #2a3132;
text-decoration: none;
padding: 10px 14px;
}
#color{
margin-left: 150px;
}
#rect{
margin-left: 100px;
}
li>a:hover{
color: #763626;
cursor: pointer;
}
#canvas{
background: #66a5ad;
position: relative;
height: 1200px;
width: 100%;
}
.corners{
position: absolute;
height: 10px;
width: 10px;
background:#fff;
border: 1px solid black;
display: none;
}
.selected .corners{
display: inline-block;
}
.cornerUpLeft{
top: -5px;
left: -5px;
}
.cornerUpRight{
top: -5px;
right: -5px;
}
.cornerBtmLeft{
bottom: -5px;
left: -5px;
}
.cornerBtmRight{
bottom: -5px;
right: -5px;
}
.rectangle{
position: absolute;
}
.colorBox{
border: 1px solid black;
height: 20px;
width: 20px;
list-style: none;
}
<h1 class="header">Sketch Board</h1>
<div>
<ul class="toolbar">
<li id="load">Load</li>
<li id="save">Save</li>
<li id="rect">Rectangle</li>
<li id="oval">Oval</li>
</ul>
<hr>
</div>
<div class="canvas" id="canvas">
</div>
Related
I'm trying to dynamically make all borders disappear except the newest created container's border I have tried the commented out section of the JavaScript. Can someone please provide an explanation/example of how this can be done?
function countButtonLinks() {
var elementGroups = document.getElementById('containsAll');
if(elementGroups.children.length == 0) {
var numID = 1;
}
if(elementGroups.children.length == 1) {
var numID = 2;
}
if(elementGroups.children.length == 2) {
var numID = 3;
}
if(elementGroups.children.length == 3) {
var numID = 4;
}
if(elementGroups.children.length == 4) {
var numID = 5;
}
if(elementGroups.children.length == 5) {
var numID = 6;
}
return numID;
}
function createContainer() {
if(document.getElementById('containsAll').children.length < 6) {
var elementA = document.createElement("span");
var elementAInnerTxt = document.createElement("div");
elementA.id = 'elem' + countButtonLinks();
elementAInnerTxt.id = 'elemInner' + countButtonLinks();
elementA.className = 'elem1';
elementAInnerTxt.className = 'elemInner1';
elementA.appendChild(elementAInnerTxt);
document.getElementById('containsAll').appendChild(elementA);
}
}
.containsAll {
width: 91%;
height: 75%;
position: absolute;
float: left;
margin-top: 1%;
margin-left: 1%;
background-color: transparent;
z-index: 91;
border: 1px #000000 solid;
border-radius: 7px;
padding: 5px;
}
.elem1 {
max-width: 100%;
max-height: 100%;
min-width: 100px;
min-height: 60px;
float: left;
background-color: transparent;
border: 1px #333333 solid;
border-radius: 5px;
}
.elemInner1 {
max-width: 100%;
max-height: 100%;
min-width: 100px;
min-height: 60px;
float: left;
background-color: transparent;
padding: 5px;
}
.buttonClass {
width: 100px;
height: 50px;
}
<button class="buttonClass" type="button" onclick="createContainer();">Click Me</button>
<div id="containsAll" class="containsAll"></div>
Please, no JQuery.
function countButtonLinks(){
var elementGroups = document.getElementById('containsAll');
// you don't need to use 'var numID'
return elementGroups.children.length + 1;
}
function createContainer(){
if(document.getElementById('containsAll').children.length < 6){
// add code here
for(var i=0;i<document.getElementById('containsAll').children.length;i++){
document.getElementById('containsAll').children[i].style.border = '0 none';
}
var elementA = document.createElement("span");
//...
Simply call the existing children of the element and remove the border before inserting
another element:
function countButtonLinks(){
var elementGroups = document.getElementById('containsAll');
var groupLength = elementGroups.children.length;
return groupLength++;
}
function createContainer() {
var containsAll = document.getElementById('containsAll'),
childrenLength = containsAll.children.length;
if (childrenLength >= 6) {
return; // Bail immediately since we only need to add a new element if the children's length is less than 6
}
// Call previous children
for ( var i = 0; i < childrenLength; i++ ) {
let child = containsAll.children[i];
// You can add a new class here that will remove the border
// but in this example, we'll use the style attribute to remove the border
child.style.border = 0;
}
// Now, add the new element
var elementA = document.createElement("span");
var elementAInnerTxt = document.createElement("div");
elementA.id = 'elem' + countButtonLinks();
elementAInnerTxt.id = 'elemInner' + countButtonLinks();
elementA.className = 'elem1';
elementAInnerTxt.className = 'elemInner1';
elementA.appendChild(elementAInnerTxt);
containsAll.appendChild(elementA);
}
Also, if you're going to use an element multiple times inside a function, make it a habit to store that element in a variable so you don't repeatedly calls the document.getElementById function.
You can accomplish this using the CSS :last-child selector
var container = document.getElementById('container');
function count_button_links()
{
return container.children.length + 1;
}
function new_container()
{
if (count_button_links() > 6) return false;
let span = document.createElement('span');
span.id = 'el_' + count_button_links();
span.className = 'box';
container.appendChild(span);
}
#container {
width: 100%;
background-color: transparent;
border: 1px solid #000;
border-radius: 7px;
padding: 5px;
display:flex;
height:200px;
}
.box {
flex:0 0 100px;
height:60px;
background-color: transparent;
border-radius: 5px;
}
.box:last-child{
border:1px solid #333;
}
button {
width: 100px;
height: 50px;
}
<button type="button" onclick="new_container();">Click Me</button>
<div id="container"></div>
I'm trying to create a circle navigation button to follow mouse movement when the cursor is inside a certain box.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
pro.addEventListener("mouseover", function() {
var e = window.event;
var x = e.clientX;
var y = e.clientY;
cer.style.top = y + "px";
cer.style.left = x + "px";
cer.style.transition = "2s";
});
pro.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
so it actually follows the first position of the mouse inside the black bordered box, i want it to update the cursor positioning every time and follow it, also i don't want the red circle to go out the red box, any suggestion? please javascript only not jquery, thanks!
The main problem is your usage of window.event and wrong event handlers.
Here's a solution that uses standard event handling:
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
var proR = pro.getBoundingClientRect();
var cirR = cer.getBoundingClientRect();
// radii
var rW = (cirR.right - cirR.left) / 2;
var rH = (cirR.bottom - cirR.top) / 2;
// page coords of center
var oX = (proR.right + proR.left) / 2;
var oY = (proR.bottom + proR.top) / 2;
var x, y;
// max movement
var max = 15;
function setPos(x, y) {
cer.style.left = (x + oX - rW) + "px";
cer.style.top = (y + oY - rH) + "px";
}
pro.addEventListener("mouseleave", function() {
setPos(0, 0);
});
pro.addEventListener("mousemove", function(e) {
// 0,0 is at center
x = e.clientX - oX;
y = e.clientY - oY;
// limit to max
if (x < -max) x = -max;
if (x > max) x = max;
if (y < -max) y = -max;
if (y > max) y = max;
// set circle position
setPos(x, y);
});
setPos(0, 0);
#prova {
display: inline-block;
border: 1px solid black;
padding: 40px;
}
#innercircle {
width: 120px;
height: 120px;
border: 1px solid red;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 50%;
transition: .5s;
position: absolute;
pointer-events: none;
}
#prova,
#innercircle,
#cerchio {
box-sizing: border-box;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
I've also changed the calculation to
determine the x,y values such that the center of the area is (0, 0)
limit the values to a set boundary
add back the offset to position the circle
Your main problem is that you're using 'mouseover'. This event only activates when the mouse enters the element. This way, if works the first time you move over the rectangle, or when you move between the black and red rectangles.
If you use 'mousemove', it works right.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
pro.addEventListener("mousemove", function() {
var e = window.event;
var x = e.clientX;
var y = e.clientY;
cer.style.top = y + "px";
cer.style.left = x + "px";
cer.style.transition = "2s";
});
pro.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
"mousemove" is the event you want to track for this as you want the position of the mouse as it moves inside the element. You should also pass the event as a callback to the event handler
I also fixed the positioning using the getBoundingClientRect() method.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
var innerC = document.getElementById('innercircle');
innerC.addEventListener("mousemove", function(e) {
var square = this.getBoundingClientRect();
var squareX = square.x;
var squareY = square.y;
var squareWidth = square.width;
var squareHeight = square.height;
var mouseX = e.clientX;
var mouseY= e.clientY;
var x = e.clientX;
var y = e.clientY;
cer.style.top = (-squareY + mouseY - (squareHeight / 2 - 15)) + "px";
cer.style.left = (-squareX + mouseX - (squareWidth / 2 - 15)) + "px";
cer.style.transition = "2s";
});
innerC.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
z-index: -1;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
z-index: 2;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
I am 3th year at college and for web design class we are manually drawing canvas elements. Which is very boring for me so I tried to make some 2D paint where I can do it by mouse where on the other end it writes code by itself.
I managed to do this much even tho is not "much" but now I am wondering is there a way to undo some script to remove it from the code? One way would be to append new canvas and do moves by one less but is there something to delete existing ones but not to recreate new ones over and over again?
In this example down below (try by full screen), when I add new lines I add new moves to the array and when I finish at the starting point I can draw new element. But every time I add new line I re create or draw lines over existing ones and new lines so it shows as one element where I could fill style and so on.
By doing that you will see that the adding lines over existing ones create a little darker bolder line, and because of that I would like to know if there is some way to delete or undo those lines and add whole new ones without puting em over existing ones.
$(document).ready(function(){
var mainCanvas = $('#mainCanvas')[0].getContext('2d');
var coordsCanvas = $('#coordsCanvas')[0].getContext('2d');
var moves = [];
$('#newCoords').click(function(){
var mainCanvasWidth = $('#mainCanvas').width();
$(this).parent().prepend('<input class="input-class" id="x-n0" placeholder="X number of blocks"><input class="input-class" id="y-n0" placeholder="Y number of blocks"> <span class="notes">Note: canvas full width is: '+Math.floor(mainCanvasWidth)+'px. </span><button id="saveCoords">Save</button>')
$(this).remove();
});
$(document).on('click','#saveCoords',function(){
var x = $(this).siblings('input#x-n0').val(),
y = $(this).siblings('input#y-n0').val(),
mainCanvasWidth = $('#mainCanvas').width(),
mainCanvasHeight = $('#mainCanvas').height(),
xWidthPx = Math.floor(mainCanvasWidth/x),
yHeightPx = Math.floor(mainCanvasHeight/y);
$('#coordsCanvas, #mainCanvas').attr('width', Math.floor(xWidthPx*x));
$('#coordsCanvas, #mainCanvas').attr('height', Math.floor(yHeightPx*y));
var marginLeftRight = 'calc(50% - '+Math.floor(xWidthPx*x)/2+'px)';
$('#coordsCanvas, #mainCanvas').css({'width':Math.floor(xWidthPx*x)+'px','height':Math.floor(yHeightPx*y)+'px','left': marginLeftRight, 'top':'10vh'});
for(var i=0; i<x-1; i++){
coordsCanvas.beginPath();
coordsCanvas.moveTo(Math.floor(xWidthPx+(xWidthPx*i)), 0);
coordsCanvas.lineTo(Math.floor(xWidthPx+(xWidthPx*i)), Math.floor(yHeightPx*y));
coordsCanvas.stroke();
coordsCanvas.closePath();
}
for(var i=0; i<y-1; i++){
coordsCanvas.beginPath();
coordsCanvas.moveTo(0 ,Math.floor(yHeightPx+(yHeightPx*i))+1);
coordsCanvas.lineTo(Math.floor(xWidthPx*x), Math.floor(yHeightPx+(yHeightPx*i))+1);
coordsCanvas.stroke();
coordsCanvas.closePath();
}
$(this).parent().html('<label for="#mouse-position"><input type="checkbox" id="mouse-position">Show mouse position</label><span class="notes">X = '+Math.floor(xWidthPx)+'px; Y = '+Math.floor(yHeightPx)+'px;</span><div class="tools"><button id="line">Lines</button></div>');
});
$(document).on( "change", "#mouse-position", function() {
if($('input[id="mouse-position"]:checked').length === 1){
$('#mouse-coords').css('display','block');
}else{
$('#mouse-coords').css('display','none');
}
});
$(document).on( "click", "#line", function() {
$(this).css('background','silver');
$('#mainCanvas').css({'cursor':'url(./pen.png) 0 24, auto'});
});
$(document).on( "click", "#mainCanvas", function(e) {
var cursor = $('#mainCanvas').css('cursor');
var strokeStyle = $('#strokestyle').val();
if(~cursor.indexOf('pen.png')){
var posX = $(this).position().left,
posY = $(this).position().top;
if(moves[0]==='beginPath'){
if(Object.keys(moves[1])[0]==='moveTo'){
var len = moves.length-1,
nowpos = Math.floor((e.pageX - posX)) + ',' + Math.floor((e.pageY - posY)),
renderDrawing = [];
renderDrawing.push({'func': 'beginPath', init: function(){ mainCanvas.beginPath(); }});
if(moves[len]!=="stroke" || moves[len]!=="closePath"){
for(var ee=1; ee<moves.length; ee++){
if(Object.keys(moves[ee])[0]==="moveTo"){
var mtp = moves[ee]['moveTo'],
pos = mtp.split(',');
renderDrawing.push({func: 'moveTo', val: pos, init: function(){
mainCanvas.moveTo(this.val[0], this.val[1]);
}});
}else if(Object.keys(moves[ee])[0]==="lineTo"){
var mtp = moves[ee]['lineTo'],
pos = mtp.split(',');
renderDrawing.push({func: 'lineTo', val: pos, init: function(){
mainCanvas.lineTo(this.val[0], this.val[1]);
}});
}
}
var nowX = Math.floor((e.pageX - posX));
var nowY = Math.floor((e.pageY - posY));
var nowXY = nowX + ',' + nowY;
moves.push({'lineTo':nowXY});
renderDrawing.push(
{func: 'lineTo', val: nowXY, init: function(){
mainCanvas.lineTo(this.val.split(',')[0], this.val.split(',')[1]);
}},
{func: 'stroke', init: function(){ mainCanvas.stroke(); }},
{func: 'closePath', init: function(){ mainCanvas.closePath(); }});
for(var q=0; q<renderDrawing.length; q++){
if(renderDrawing[q]['func']!=="beginPath" && renderDrawing[q]['func']!=="closePath" && renderDrawing[q]['func']!=="stroke"){
renderDrawing[q].init();
}else renderDrawing[q].init();
}
console.log(moves);
if(Object.keys(moves[len])[0]==="lineTo" && nowpos===moves[1]['moveTo']){
moves = [];
}
}
}
}else{
mainCanvas.beginPath();
mainCanvas.moveTo(Math.floor(e.pageX - posX) , Math.floor(e.pageY - posY));
moves.push('beginPath',{'moveTo':Math.floor((e.pageX - posX)) + ',' + Math.floor((e.pageY - posY))});
console.log(moves);
}
}
});
$(document).on('mousemove', "#mainCanvas", function(e){
var parentOffset = $('#mainCanvas').offset();
var relX = e.pageX - parentOffset.left;
var relY = e.pageY - parentOffset.top;
$('#mouse-coords').css({
left: e.pageX + 20,
top: e.pageY
}).text( "X: " + Math.floor(relX) + ", Y: " + Math.floor(relY) );
});
});
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
box-sizing: border-box;
}
body {
overflow: hidden;
font-size: 100%;
}
.container {
width: 100vw;
height: 100vh;
padding-right: 5vw;
padding-left: 5vw;
padding-top: 10vh;
padding-bottom: 5vh;
overflow: hidden;
position: relative;
}
canvas {
width: 90vw;
height: 85vh;
border: 1px solid #000;
float: left;
}
.toolsBar {
width: calc(100% - 10vw);
position: absolute;
top: 5px;
left: 5vw;
border: 1px solid #000;
height: calc(10vh - 10px);
overflow: hidden;
overflow-y: auto;
}
button {
color: #fff;
background: skyblue;
border: 0;
border-radius: 5px;
margin: 5px;
padding: 15px;
cursor: pointer;
float: left;
}
.input-class {
border-radius: 5px;
margin: 5px;
padding: 15px;
float: left;
border: 1px solid #e0e0e0;
outline: none;
}
.notes {
display: inline-block;
height: 60px;
text-align: center;
float: left;
color: red;
line-height: 60px;
}
#mouse-coords {
position: absolute;
display: none;
background: #000;
padding: 2px;
color: #fff;
}
label[for="#mouse-position"] {
display: inline-block;
height: 60px;
text-align: center;
line-height: 60px;
font-size: 1.2rem;
float: left;
padding: 5px;
}
label>input {
height: 1.2rem;
width: 1.2rem;
}
.coordsCanvas {
position: absolute;
z-index: 100;
}
#mainCanvas {
background: rgba(255,255,255,.5);
position: absolute;
z-index: 200;
}
.tools {
width: auto;
overflow: hidden;
overflow-y: auto;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="toolsBar">
<button id="newCoords">X & Y</button>
</div>
<div id="mouse-coords"></div>
<canvas class="coordsCanvas" id="coordsCanvas"></canvas>
<canvas id="mainCanvas"></canvas>
</div>
I write some code for to convert svg to inline svg and take screenshot of that div . Please check .Please copy this code int to your local host and test it . Because screen shot is different in different width .
https://jsfiddle.net/7bqukhff/15/
<link href="style.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="test">
<div class="description-div">
<p>Sample description</p>
</div>
<div class="img-div" id="img-div"></div>
</div>
<form class="cf">
<div class="half left cf">
<input type="text" name="user-name" required>
<select name="design-name" class="desgign-class" required>
<option value="" >select</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<input type="submit" name="submit" value="submit" class="submit">
</div>
</form>
</div>
<div class="new">
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>
</div>
<script>
$(function() {
$(".desgign-class").on("change",function(){
var op=$(this).val();
if(op!=0){
$('.btn').show();
$('.img-div').html('');
if(op==2){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='https://istack.000webhostapp.com/1tf.svg'>");
}
}
if(op==3){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='https://istack.000webhostapp.com/_1tf.svg'>");
}
}
if(op==4){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='http://svgur.com//i/1yP.svg'>");
}
}
}
else{
$('.btn').hide();
}
$('img').each(function() {
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if (typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
(function(exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function(el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
var wrapper = document.getElementById('img-div');
html2canvas(wrapper, {
onrendered: function(canvas) {
function getOffset(el) {
el = el.getBoundingClientRect();
return {
left: el.left + window.scrollX,
top: el.top + window.scrollY
}
}
var cachedCanvas = canvas;
var ctx = canvas.getContext('2d');
var svgs = document.querySelectorAll('svg');
svgs.forEach(function(svg) {
var svgWidth = svg.width.baseVal.value;
var svgHeight = svg.height.baseVal.value;
var svgLeft = getOffset(svg).left - 40;
var svgTop = getOffset(svg).top - 62;
var offScreenCanvas = document.createElement('canvas');
offScreenCanvas.width = svgWidth;
offScreenCanvas.height = svgHeight;
canvg(offScreenCanvas, svg.outerHTML);
ctx.drawImage(cachedCanvas, 0, 0);
ctx.drawImage(offScreenCanvas, svgLeft, svgTop);
});
canvas.toBlob(function(blob) {
saveAs(blob, 'myScreenshot.png');
});
}
});
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function(e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
screenshotPage();
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
});
</script>
html,
body {
background: #f1f1f1;
font-family: 'Merriweather', sans-serif;
padding: 1em;
}
form {
border: 2px solid blue;
float: left;
max-width: 300px;
padding: 5px;
text-align: center;
width: 30%;
}
.img-div {
border: 1px solid black;
display: block;
float: left;
margin-right: 86px;
overflow: hidden;
width: 50%;
padding: 10px;
}
.btn {
display: none;
overflow: hidden;
width: 100%;
}
.new{
display: block;
overflow: hidden;
width: 100%;
}
.description-div {
border: 2px solid green;
float: left;
margin-right: 32px;
padding: 3px;
width: 13%;
}
.submit {
background: wheat none repeat scroll 0 0;
border: 1px solid red;
cursor: pointer;
}
input,
textarea {
border: 0;
outline: 0;
padding: 1em;
#include border-radius(8px);
display: block;
width: 100%;
margin-top: 1em;
font-family: 'Merriweather', sans-serif;
#include box-shadow(0 1px 1px rgba(black, 0.1));
resize: none;
&:focus {
#include box-shadow(0 0px 2px rgba($red, 1)!important);
}
}
#input-submit {
color: white;
background: $red;
cursor: pointer;
&:hover {
#include box-shadow(0 1px 1px 1px rgba(#aaa, 0.6));
}
}
But here (1) when i take screen shot of img-div the screenshot is different from original representation. Why it happen ?
(2) Also in option 4 screenshot the svg is not appearing . Actually i have too many option and too many images . Now i only write 3 options .
(3) Is it possible for to save this screen shot to server[specific folder] when user submitting the form ?
(4) Is there any other method without using html canvas ?
(5) LIKE HOW SCREEN SHOT OPTION IN COMPUTER WORKS ? or browser extension like https://chrome.google.com/webstore/detail/awesome-screenshot-screen/nlipoenfbbikpbjkfpfillcgkoblgpmj?hl=en .
https://www.youtube.com/watch?v=3766n-SDPNc&feature=youtu.be
Short form : i have a website . In which user can select any svg from
the given svg list . When user select one svg then that svg is
converted to inline svg displayed in one div . Also user can move
that svg to any portion of the div . After everything then user will
fill a form and submit . At the time of submit we want to download the
screen shot of that div then we understand user select which colour ,
where the svg imge is place etc
Please check below mentioned solution. I just tried to cover up your issue.
$(function() {
$(".desgign-class").on("change",function(){
var op=$(this).val();
if(op!=0){
$('.btn').show();
$('.img-div').html('');
if(op==2){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='https://istack.000webhostapp.com/1tf.svg'>");
}
}
if(op==3){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='https://istack.000webhostapp.com/_1tf.svg'>");
}
}
if(op==4){
for(var i = 0;i<op;i++){
$('.img-div').append("<img src='http://svgur.com//i/1yP.svg'>");
}
}
}
else{
$('.btn').hide();
}
$('img').each(function() {
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if (typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
(function(exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function(el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
var wrapper = document.getElementById('img-div');
html2canvas(wrapper, {
onrendered: function(canvas) {
function getOffset(el) {
el = el.getBoundingClientRect();
return {
left: el.left + window.scrollX,
top: el.top + window.scrollY
}
}
var cachedCanvas = canvas;
var ctx = canvas.getContext('2d');
var svgs = document.querySelectorAll('svg');
var sleft = 0;
svgs.forEach(function(svg) {
var svgWidth = svg.width.baseVal.value;
var svgHeight = svg.height.baseVal.value;
var svgLeft = 10;
var svgTop = getOffset(svg).top - 40;
var offScreenCanvas = document.createElement('canvas');
offScreenCanvas.width = svgWidth;
offScreenCanvas.height = svgHeight;
canvg(offScreenCanvas, svg.outerHTML);
ctx.drawImage(cachedCanvas, 0, 0);
ctx.drawImage(offScreenCanvas, svgLeft, svgTop);
});
canvas.toBlob(function(blob) {
saveAs(blob, 'myScreenshot.png');
});
}
});
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function(e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
screenshotPage();
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
});
#import url(https://fonts.googleapis.com/css?family=Merriweather);
$red: #e74c3c;
*,
*:before,
*:after {
#include box-sizing(border-box);
}
html,
body {
background: #f1f1f1;
font-family: 'Merriweather', sans-serif;
padding: 1em;
}
h1 {
text-align: center;
color: #a8a8a8;
#include text-shadow(1px 1px 0 rgba(white, 1));
}
form {
border: 2px solid blue;
float: left;
max-width: 300px;
padding: 5px;
text-align: center;
width: 30%;
}
.img-div {
border: 1px solid black;
display: block;
float: left;
margin-right: 86px;
overflow: hidden;
width: 50%;
padding: 10px;
}
.btn {
display: none;
overflow: hidden;
width: 100%;
}
.new{
display: block;
overflow: hidden;
width: 100%;
}
.description-div {
border: 2px solid green;
float: left;
margin-right: 32px;
padding: 3px;
width: 13%;
}
.submit {
background: wheat none repeat scroll 0 0;
border: 1px solid red;
cursor: pointer;
}
input,
textarea {
border: 0;
outline: 0;
padding: 1em;
#include border-radius(8px);
display: block;
width: 100%;
margin-top: 1em;
font-family: 'Merriweather', sans-serif;
#include box-shadow(0 1px 1px rgba(black, 0.1));
resize: none;
&:focus {
#include box-shadow(0 0px 2px rgba($red, 1)!important);
}
}
#input-submit {
color: white;
background: $red;
cursor: pointer;
&:hover {
#include box-shadow(0 1px 1px 1px rgba(#aaa, 0.6));
}
}
textarea {
height: 126px;
}
}
.half {
float: left;
width: 48%;
margin-bottom: 1em;
}
.right {
width: 50%;
}
.left {
margin-right: 2%;
}
#media (max-width: 480px) {
.half {
width: 100%;
float: none;
margin-bottom: 0;
}
}
/* Clearfix */
.cf:before,
.cf:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.cf:after {
clear: both;
}
.half.left.cf > input {
margin: 5px;
}
#media print {
html, body { padding:0 !important;margin:0 !important; }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="test">
<div class="description-div">
<p>Sample description</p>
</div>
<div class="img-div" id="img-div"></div>
</div>
<form class="cf">
<div class="half left cf">
<input type="text" name="user-name" required>
<select name="design-name" class="desgign-class" required>
<option value="" >select</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
<input type="submit" name="submit" value="submit" class="submit">
</div>
</form>
</div>
<div class="new">
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>
</div>
As far as I can tell, this is a working version: https://jsfiddle.net/7bqukhff/16/
The difference comes from the way you are drawing onto the offscreenCanvas.
Here's what happens in your code:
You are setting the dimensions of the offscreenCanvas to the width and height of the SVG (instead of the width & height of the wrapper) in lines 108 & 109
You subtract something (40 and 62) from the left & top position of the SVG. This position is referring to the position on the page rather than the relative position of the SVG within the wrapper.
You draw the SVG onto the canvas with page-coordinates instead of relative coordinates
The fix looks like this:
First, set the dimensions of the canvas to the dimensions of the wrapper:
var wrapperRect = wrapper.getBoundingClientRect()
// ...
offScreenCanvas.width = wrapperRect.width;
offScreenCanvas.height = wrapperRect.height;
Then, draw the svg using relative coordinates:
var svgLeft = getOffset(svg).left - wrapper.left;
var svgTop = getOffset(svg).top - wrapper.top;
This seems to work as you need.
P.S.: The option "4" doesn't work but that's due to it using HTTP on an HTTPS site, so it's not loaded due to security restrictions.
I have a slider with a pop-up that shows the current value of the slider.
but I want it only appears if I click on the slider and disappears when I do not click
is there a way to do it?
Below is my css js and html code
html:
<input type="range" id="myrange" name="myrange" class="zoom-range" min="0.25" max="2.00" step="0.01"/>
<output id="rangeHover" for="myrange" onmouseover="value = myrange.valueAsNumber;"></output>
js:
function modifyOffset() {
var el, newPoint, newPlace, offset, siblings, k;
width = this.offsetWidth;
newPoint = (this.value - this.getAttribute("min")) / (this.getAttribute("max") - this.getAttribute("min"));
offset = -1;
if (newPoint < 0) { newPlace = 0; }
else if (newPoint > 1) { newPlace = width; }
else { newPlace = width * newPoint + offset; offset -= newPoint;}
siblings = this.parentNode.childNodes;
for (var i = 0; i < siblings.length; i++) {
sibling = siblings[i];
if (sibling.id == this.id) { k = true; }
if ((k == true) && (sibling.nodeName == "OUTPUT")) {
outputTag = sibling;
}
}
outputTag.style.left = newPlace + "px";
outputTag.style.marginLeft = offset + "%";
outputTag.innerHTML = this.value;
}
function modifyInputs() {
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].getAttribute("type") == "range") {
inputs[i].onchange = modifyOffset;
// the following taken from http://stackoverflow.com/questions/2856513/trigger-onchange-event-manually
if ("fireEvent" in inputs[i]) {
inputs[i].fireEvent("onchange");
} else {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
inputs[i].dispatchEvent(evt);
}
}
}
}
window.onload = modifyInputs;
css:
output {
position: absolute;
background-image: linear-gradient(#FAFAD2, #FAFAD2);
width: 30px;
height: 15px;
text-align: center;
color: black;
border-radius: 5px;
display: block;
bottom: 120%;
margin-top:5000px;
font-size:11px;
left: 100%;
}
output:after {
content: "";
position: absolute;
width: 0px;
height: 0px;
border-top: 10px solid #FAFAD2;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
top: 100%;
left: 100%;
margin-left: -26px;
margin-top: -1px;
}
#rangeHover{
display: block;
position: relative;
margin: -50px;
padding-right:10px;
padding-left:10px;
}
Thanks for help!
you could add to css:
output
{
display:none
}
input:hover + output
{
display:block;
}
UPDATE
tooltip visible on click:
input:active+ output
{
display:block;
}