nvd3 export to img cropping image - javascript

im trying to export a NVD3 graph using this tutorials:
http://www.coffeegnome.net/converting-svg-to-png-with-canvg/
SVG to Canvas with d3.js
It works perfectly but my result image is cropped to 300 x 150, how can I export the whole image?
My code is this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Export D3 to image</title>
<link rel="stylesheet" type="text/css" href="css/nv.d3.css">
<script language="javascript" type="text/javascript" src="js/jquery.min.js"></script>
<script language="javascript" type="text/javascript" src="js/d3.min.js"></script>
<script language="javascript" type="text/javascript" src="js/nv.d3.js"></script>
</head>
<body>
<svg id="basicChart1"></svg>
<script>
createGraphs();
function createGraphs() {
nv.addGraph(function () {
chart1 = nv.models.lineChart()
.useInteractiveGuideline(true)
;
chart1.xAxis
.axisLabel('Time (ms)')
.tickFormat(d3.format(',r'))
;
chart1.yAxis
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f'))
;
d3.select('#basicChart1')
.datum(data())
.call(chart1)
;
nv.utils.windowResize(chart1.update);
return chart1;
});
console.log("Graficas Creadas");
}
function data() {
var sin = [];
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i / 10)});
}
return [
{
values: sin,
key: 'Sine Wave',
color: '#ff7f0e'
}
];
}
// Tutorials:
// http://www.coffeegnome.net/converting-svg-to-png-with-canvg/
// Create an export button
d3.select('body')
.append("button")
.html("Export")
.on("click", saveSVG)
.attr('class', 'btn btn-success');
var width = 300, height = 100;
// Create the export function - this will just export
// the first svg element it finds
function saveSVG() {
// get styles from all required stylesheets
// http://www.coffeegnome.net/converting-svg-to-png-with-canvg/
var style = "\n";
var requiredSheets = ['nv.d3.css']; // list of required CSS
for (var i = 0; i < document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
if (sheet.href) {
if (requiredSheets.indexOf(sheet.href.split('/').pop()) !== -1) {
if (sheet.rules) {
for (var j = 0; j < sheet.rules.length; j++) {
style += (sheet.rules[j].cssText + '\n');
}
}
}
}
}
var svg = d3.select("#basicChart1"),
serializer = new XMLSerializer();
// prepend style to svg
svg.insert('defs', ":first-child");
d3.select("svg defs")
.append('style')
.attr('type', 'text/css')
.html(style);
// generate IMG in new tab
var svgStr = serializer.serializeToString(svg.node());
var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgStr)));
var image = new Image();
image.src = imgsrc;
window.open().document.write('<img src="' + image.src + '"/>');
}
;
</script>
</body>
</html>

I'll answer my own question:
The problem was on the SVG Width and Height attributes:
<svg id="basicChart1"></svg>
So i only needed to add the calculated Width and Height values to the svg tag before the generation of the image:
var serializer = new XMLSerializer();
var svg = d3.select("#basicChart1");
svg.attr('width', svg.node().clientWidth);
svg.attr('height', svg.node().clientHeight);
svg.insert('defs', ":first-child");
d3.select("svg defs")
.append('style')
.attr('type', 'text/css')
.html(style);

Related

I want to convert paper.js Examples from paperscript to javascript

I am Japanese and I apologize for my unnatural English, but I would appreciate it if you could read it.
I learned how to convert paperscript to javascript from the official documentation.
Its means are as follows
Change the type attribute of the script tag to text/paperscript. <script type="text/paperscript" src="./main.js"></script>
Enable Paperscope for global use.  paper.install(window)
Specify the target of the canvas. paper.setup(document.getElementById("myCanvas"))
Write the main code in the onload window.onload = function(){ /* add main code */ }
Finally, add paper.view.draw()
The onFrame and onResize transforms as follows. view.onFrame = function(event) {}
onMouseDown, onMouseUp, onMouseDrag, onMouseMove, etc. are converted as follows. var customTool = new Tool(); customTool.onMouseDown = function(event) {};
I have tried these methods, but applying these to the Examples on the paper.js official site does not work correctly.
The following code is the result of trying these.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://unpkg.com/paper"></script>
<script type="text/javascript" src="./main.js"></script>
<title>Document</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
paper.install(window);
console.log("run test")
var myCanvas = document.getElementById("myCanvas")
var customTool = new Tool();
window.onload = function(){
paper.setup(myCanvas)
var points = 25;
// The distance between the points:
var length = 35;
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++)
path.add(start + new Point(i * length, 0));
customTool.onMouseMove=function(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
var vector = segment.point - nextSegment.point;
vector.length = length;
nextSegment.point = segment.point - vector;
}
path.smooth({ type: 'continuous' });
}
customTool.onMouseDown=function(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
customTool.onMouseUp=function(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
view.draw();
}
The original paperscript can be found here.
What is the problem with this code?
Thank you for reading to the end!
The var vector in the for loop is not getting the correct values in your code. Change the math operators and it will work like the paperjs demo.
Math operators (+ - * /) for vector only works in paperscript. In Javascript, use .add() .subtract() .multiply() .divide(). see http://paperjs.org/reference/point/#subtract-point
// paperscript
segment.point - nextSegment.point
// javascript
segment.point.subtract(nextSegment.point)
Here's a working demo of your example
paper.install(window);
console.log("run test")
var myCanvas = document.getElementById("myCanvas")
var customTool = new Tool();
window.onload = function() {
paper.setup(myCanvas)
var points = 15; //25
// The distance between the points:
var length = 20; //35
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++) {
path.add(start + new Point(i * length, 0));
}
customTool.onMouseMove = function(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
//var vector = segment.point - nextSegment.point;
var vector = segment.point.subtract(nextSegment.point);
vector.length = length;
//nextSegment.point = segment.point - vector;
nextSegment.point = segment.point.subtract(vector);
}
path.smooth({
type: 'continuous'
});
}
customTool.onMouseDown = function(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
customTool.onMouseUp = function(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
view.draw();
}
html,
body {
margin: 0
}
canvas {
border: 1px solid red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://unpkg.com/paper"></script>
<!-- you can add this back in -->
<!-- <script type="text/javascript" src="./main.js"></script> -->
<title>Document</title>
</head>
<body>
<!-- set any size you want, or use CSS/JS to make this resizable -->
<canvas id="myCanvas" width="600" height="150"></canvas>
</body>
</html>

Paper js stops redrawing after loading another script

I'm using paper js to draw an animated set of rectangles. Since there will be several HTML pages in this project, I tried adding the menu HTML programmatically using javascript. However, once the menu script loads, paper js stops redrawing.
I used a timer to delay the loading of the menu script to ascertain if it was any other issue. The animation definitely plays normally right before the menu script loads.
Any other element added programmatically works fine. It's the only paper that stops redrawing.
HTML
<head>
<script src="./scripts/paper-full.js"></script>
<script type="text/javascript" src="./scripts/menu.js"></script>
<script
type="text/paperscript"
src="./scripts/paper.js"
canvas="myCanvas"
></script>
<!-- <link rel="stylesheet" href="./styles/style.css" /> -->
<link
href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap"
rel="stylesheet"
/>
</head>
<body id="body">
<div id="main">
<label id="stats"></label>
<canvas id="myCanvas" resize></canvas>
</div>
</body>
MENU
var label = '<label id="stats"></label>';
var divO = '<div id="menu" class="menu">';
var divC = "</div>";
var html =
'Home ProjectsBlog About';
setTimeout(() => {
document.body.innerHTML += label + divO + html + divC;
}, 500);
PAPER
var length = 35;
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var start = view.center / [10, 1];
for (var i = 0; i < points; i++)
path.add(start + new Point(i * length, 0));
function onMouseMove(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
var vector = segment.point - nextSegment.point;
vector.length = length;
nextSegment.point = segment.point - vector;
}
path.smooth({ type: 'continuous' });
}
function onMouseDown(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
function onMouseUp(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
Your problem comes from the fact that you are resetting the document.body.innerHTML and this somehow breaks Paper.js coupling with the canvas.
What I would suggest is using a dedicated element to insert your dynamic content into the DOM, rather that injecting it into the <body> directly.
Here is an updated code demonstrating the solution. Have a close look at the lines:
<div id="menu-container"></div>
document.querySelector('#menu-container').innerHTML = label + divO + html + divC;
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/paper"></script>
<link
href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap"
rel="stylesheet"
/>
</head>
<body id="body">
<div id="main">
<label id="stats"></label>
<canvas id="myCanvas" resize></canvas>
</div>
<div id="menu-container"></div>
<script type="text/javascript">
var label = '<label id="stats"></label>';
var divO = '<div id="menu" class="menu">';
var divC = "</div>";
var html =
'Home ProjectsBlog About';
document.querySelector('#menu-container').innerHTML = label + divO + html + divC;
</script>
<script type="text/paperscript" canvas="myCanvas">
var length = 35;
var path = new Path({
strokeColor: '#E4141B',
strokeWidth: 20,
strokeCap: 'round'
});
var points = 20
var start = view.center / [10, 1];
for (var i = 0; i < points; i++)
path.add(start + new Point(i * length, 0));
function onMouseMove(event) {
path.firstSegment.point = event.point;
for (var i = 0; i < points - 1; i++) {
var segment = path.segments[i];
var nextSegment = segment.next;
var vector = segment.point - nextSegment.point;
vector.length = length;
nextSegment.point = segment.point - vector;
}
path.smooth({ type: 'continuous' });
}
function onMouseDown(event) {
path.fullySelected = true;
path.strokeColor = '#e08285';
}
function onMouseUp(event) {
path.fullySelected = false;
path.strokeColor = '#e4141b';
}
</script>
</body>
</html>

Get the focused image element inside a contenteditable div

I need to modify a pasted image inside a contenteditable div: resize it proportionately, add borders, etc... Perhaps this can be achieved by adding a className that will alter the necessary CSS properties.
The problem is that I don't know how to reference the focused, i.e. the active, the clicked-upon image or any element for that matter.
This is the HTML that I am trying to use
<!DOCTYPE html>
<html>
<body>
<div contenteditable="true">This is a div. It is editable. Try to change this text.</div>
</body>
</html>
Using css, html and javascript
Your editable content should be inside a parent div with an id or class name, you can even have different divs for images and such.
Then it is as simple as having css like so:
#editableContentDiv img {
imgProperty: value;
}
Then you can have javascript like so:
function insertImage(){
var $img = document.querySelector("#editableContentDiv img");
$img.setAttribute('class','resize-drag');
}
Eventually if you have more than one img inside the same div you can use querySelectorAll instead of querySelector and then iterate through the img tags inside same div.
I beleive that should at least give you an idea of where to start with what you want.
Similar example
I found this gist that seems to have similar things to want you want but a bit more complicated.
function resizeMoveListener(event) {
var target = event.target,
x = (parseFloat(target.dataset.x) || 0),
y = (parseFloat(target.dataset.y) || 0);
// update the element's style
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
// translate when resizing from top or left edges
x += event.deltaRect.left;
y += event.deltaRect.top;
updateTranslate(target, x, y);
}
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.dataset.x) || 0) + event.dx,
y = (parseFloat(target.dataset.y) || 0) + event.dy;
updateTranslate(target, x, y);
}
function updateTranslate(target, x, y) {
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the position attributes
target.dataset.x = x;
target.dataset.y = y;
}
function insertImage() {
var $img = document.createElement('img');
$img.setAttribute('src', 'https://vignette.wikia.nocookie.net/googology/images/f/f3/Test.jpeg/revision/latest?cb=20180121032443');
$img.setAttribute('class', 'resize-drag');
document.querySelector(".container-wrap").appendChild($img);
var rect = document.querySelector(".container-wrap").getBoundingClientRect();
$img.style.left = rect.left;
$img.style.top = rect.top;
}
function dataTransfer() {
//cleanup
var $out = document.querySelector(".out-container-wrap");
while ($out.hasChildNodes()) {
$out.removeChild($out.lastChild);
}
//get source
var source = document.querySelector('.container-wrap')
//get data
var data = getSource(source);
//add data to target
setSource($out, data);
}
/**
* Get data from source div
*/
function getSource(source) {
var images = source.querySelectorAll('img');
var text = source.querySelector('div').textContent;
//build the js object and return it.
var data = {};
data.text = text;
data.image = [];
for (var i = 0; i < images.length; i++) {
var img = {}
img.url = images[i].src
img.x = images[i].dataset.x;
img.y = images[i].dataset.y;
img.h = images[i].height;
img.w = images[i].width;
data.image.push(img)
}
return data;
}
function setSource(target, data) {
//set the images.
for (var i = 0; i < data.image.length; i++) {
var d = data.image[i];
//build a new image
var $img = document.createElement('img');
$img.src = d.url;
$img.setAttribute('class', 'resize-drag');
$img.width = d.w;
$img.height = d.h;
$img.dataset.x = d.x;
$img.dataset.y = d.y;
var rect = target.getBoundingClientRect();
$img.style.left = parseInt(rect.left);
$img.style.top = parseInt(rect.top);
//transform: translate(82px, 52px)
$img.style.webkitTransform = $img.style.transform = 'translate(' + $img.dataset.x + 'px,' + $img.dataset.y + 'px)';
//$img.style.setProperty('-webkit-transform', 'translate('+$img.dataset.x+'px,'+$img.dataset.y+'px)');
target.appendChild($img);
}
//make a fresh div with text content
var $outContent = document.createElement('div')
$outContent.setAttribute('class', 'out-container-content');
$outContent.setAttribute('contenteditable', 'true');
$outContent.textContent = data.text;
target.appendChild($outContent);
}
interact('.resize-drag')
.draggable({
onmove: dragMoveListener,
inertia: true,
restrict: {
restriction: "parent",
endOnly: true,
elementRect: {
top: 0,
left: 0,
bottom: 1,
right: 1
}
}
})
.resizable({
edges: {
left: true,
right: true,
bottom: true,
top: true
},
onmove: resizeMoveListener
})
.resize-drag {
z-index: 200;
position: absolute;
border: 2px dashed #ccc;
}
.out-container-content,
.container-content {
background-color: #fafcaa;
height: 340px;
}
#btnInsertImage {
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="http://code.interactjs.io/interact-1.2.4.min.js"></script>
</head>
<body>
<button id="btnInsertImage" onclick="insertImage()">Insert Image</button>
<div class="container-wrap">
<div class="container-content" contenteditable="true">This is the content of the container. The content is provided along with the image. The image will be moved around and resized as required. The image can move within the boundary of the container.</div>
</div>
<button id="btnSubmit" onclick="dataTransfer()">Submit</button>
<div class="out-container-wrap">
</div>
</body>
</html>
Source
This is what I tried and it seems to be working - at least on my system, the snippet I made does not work unfortunately.
function getSelImg(){
var curObj;
window.document.execCommand('CreateLink',false, 'http://imageselectionhack/');
allLinks = window.document.getElementsByTagName('A');
for(i = 0; i < allLinks.length; i++)
{
if (allLinks[i].href == 'http://imageselectionhack/')
{
curObj = allLinks[i].firstChild;
window.document.execCommand('Undo'); // undo link
break;
}
}
if ((curObj) && (curObj.tagName=='IMG'))
{
//do what you want to...
curObj.style.border = "thick solid #0000FF";
}
}
<!DOCTYPE html>
<html>
<body>
<input type="button" onclick="getSelImg()" value="set img border">
<div contenteditable="true">This is a div.<br>
It is editable.<br>
Try to paste an image here:<br>
###########################<br>
<br>
<br>
<br>
###########################
</div>
</body>
</html>

How can you target part of svg image

So I have this similar svg image. white being transparent with black dots. I have to cover the whole background with this pattern and then target a 5x5square dot area of dots to change their color.
What is the simplest way or a common method to achieve this?
You can access elements of an SVG-image if it is embedded directly into the HTML-code. You can even create the whole SVG using JavaScript. Here is an example:
https://jsfiddle.net/da_mkay/eyskzpsc/7/
<!DOCTYPE html>
<html>
<head>
<title>SVG dots</title>
</head>
<body>
</body>
<script>
var makeSVGElement = function (tag, attrs) {
var element = document.createElementNS('http://www.w3.org/2000/svg', tag)
for (var k in attrs) {
element.setAttribute(k, attrs[k])
}
return element
}
var makeDotSVG = function (width, height, dotRadius) {
var svg = makeSVGElement('svg', { width: width, height: height, 'class': 'dot-svg' })
, dotDiameter = dotRadius*2
, dotsX = Math.floor(width / dotDiameter)
, dotsY = Math.floor(height / dotDiameter)
// Fill complete SVG canvas with dots
for (var x = 0; x < dotsX; x++) {
for (var y = 0; y < dotsY; y++) {
var dot = makeSVGElement('circle', {
id: 'dot-'+x+'-'+y,
cx: dotRadius + x*dotDiameter,
cy: dotRadius + y*dotDiameter,
r: dotRadius,
fill: '#B3E3A3'
})
svg.appendChild(dot)
}
}
// Highlight the hovered dots by changing its fill-color
var curMouseOver = function (event) {
var dotX = Math.floor(event.offsetX / dotDiameter)
, dotY = Math.floor(event.offsetY / dotDiameter)
, dot = svg.getElementById('dot-'+dotX+'-'+dotY)
if (dot !== null) {
dot.setAttribute('fill', '#73B85C')
}
}
svg.addEventListener('mouseover', curMouseOver)
return svg
}
// Create SVG and add to body
var myDotSVG = makeDotSVG(500, 500, 5)
console.log(document.body)
document.body.appendChild(myDotSVG)
</script>
</html>

Canvas waving flag HTML5

I need a little help about canvas and HTML5.
I have this code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>HTML Canvas Flag Wave</title>
<style type="text/css" media="screen">
body { background:#eee }
#flag { position:absolute; top:50%; left:50% }
</style>
<script type="text/javascript">
var h = new Image;
h.onload = function(){
var flag = document.getElementById('flag');
var amp = 20;
flag.width = h.width;
flag.height = h.height + amp*2;
flag.getContext('2d').drawImage(h,0,amp,h.width,h.height);
flag.style.marginLeft = -(flag.width/2)+'px';
flag.style.marginTop = -(flag.height/2)+'px';
var timer = waveFlag( flag, h.width/10, amp );
};
h.src = 'gkhead.jpg';
function waveFlag( canvas, wavelength, amplitude, period, shading, squeeze ){
if (!squeeze) squeeze = 0;
if (!shading) shading = 100;
if (!period) period = 200;
if (!amplitude) amplitude = 10;
if (!wavelength) wavelength = canvas.width/10;
var fps = 30;
var ctx = canvas.getContext('2d');
var w = canvas.width, h = canvas.height;
var od = ctx.getImageData(0,0,w,h).data;
// var ct = 0, st=new Date;
return setInterval(function(){
var id = ctx.getImageData(0,0,w,h);
var d = id.data;
var now = (new Date)/period;
for (var y=0;y<h;++y){
var lastO=0,shade=0;
var sq = (y-h/2)*squeeze;
for (var x=0;x<w;++x){
var px = (y*w + x)*4;
var pct = x/w;
var o = Math.sin(x/wavelength-now)*amplitude*pct;
var y2 = y + (o+sq*pct)<<0;
var opx = (y2*w + x)*4;
shade = (o-lastO)*shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData(id,0,0);
// if ((++ct)%100 == 0) console.log( 1000 * ct / (new Date - st));
},1000/fps);
}
</script>
</head>
<body>
<canvas id="flag"></canvas>
</body>
</html>
The result is this:
http://www.americkiplakari.org/zastavanovo.html
Nice waving flag, but I have a problem, I'm not so good with canvas. I want to rotate canvas, I want to top of image be fixed and waves goes from top to bottom, is it possible to do that.
Ok here is simple solution, just rotate with CSS3, put canvas in another div and you are ready to go go....
<style type="text/css" media="screen">
body { background:#eee }
#flagunustra { position:absolute; top:50%; left:50% }
#flag{
margin-top:250px;
width:414px;
transform:rotate(90deg);
-ms-transform:rotate(90deg); /* IE 9 */
-moz-transform:rotate(90deg); /* Firefox */
-webkit-transform:rotate(90deg); /* Safari and Chrome */
-o-transform:rotate(90deg); /* Opera */
}
</style>
<div id="flagunustra">
<canvas id="flag"></canvas></div>

Categories