I am using html2canvas library to take screenshot of html view.
but background-image failed to load. i am getting error message Error loading background:
here is my JSFiddle.
window.takeScreenShot = function() {
html2canvas(document.getElementById("target"), {
onrendered: function (canvas) {
document.body.appendChild(canvas);
},
useCORS:true,
logging:true,
allowTaint:true
});
}
#target{
width:300px;
height:160px;
background:lightblue;
color:#fff;
padding:10px;
background-image: url(https://static.pexels.com/photos/20974/pexels-photo.jpg);
background-repeat:no-repeat;
background-position:center center;
-o-background-size: 100%;
-moz-background-size: 100%;
-webkit-background-size: 100%;
background-size: 100%;
height: 100%;
}
#borderimg1 {
border: 10px solid transparent;
padding: 15px;
-webkit-border-image: url(https://www.w3schools.com/cssref/border.png) 30 round; /* Safari 3.1-5 */
-o-border-image: url(https://www.w3schools.com/cssref/border.png) 30 round; /* Opera 11-12.1 */
border-image: url(https://www.w3schools.com/cssref/border.png) 30 round;
}
#borderimg2 {
border: 10px solid transparent;
padding: 15px;
-webkit-border-image: url(https://www.w3schools.com/cssref/border.png) 30 stretch; /* Safari 3.1-5 */
-o-border-image: url(https://www.w3schools.com/cssref/border.png) 30 stretch; /* Opera 11-12.1 */
border-image: url(https://www.w3schools.com/cssref/border.png) 30 stretch;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<button onclick="takeScreenShot()">to image</button>
<div id="target">
<p>The border-image property specifies an image to be used as the border around an element:</p>
<p id="borderimg1">Here, the middle sections of the image are repeated to create the border.</p>
<p id="borderimg2">Here, the middle sections of the image are stretched to create the border.</p>
<p>Here is the original image:</p><img src="https://www.w3schools.com/cssref/border.png">
<p><strong>Note:</strong> Internet Explorer 10, and earlier versions, do not support the border-image property.</p>
</div>
image for error message
For Internet security reasons, trying to use an image from a different domain in a canvas causes problems. There are two html2canvas options, useCORS and proxy, which are designed to try to get around that problem.
You have to create the proxy in you project and use that into html2canvas proxy option.
Click here to view sample proxy created in different programming languages.
Usage of proxy in html2canvas(c# example)
html2canvas(document.body, {
"logging": true, //Enable log (use Web Console for get Errors and Warings)
"proxy":"html2canvasproxy.ashx",
"onrendered": function(canvas) {
var img = new Image();
img.onload = function() {
document.body.appendChild(img);
};
img.error = function() {
if(window.console.log) {
window.console.log("Not loaded image from canvas.toDataURL");
} else {
alert("Not loaded image from canvas.toDataURL");
}
};
img.src = canvas.toDataURL("image/png");
}
});
I have same problem.
It's just because of not surpoted problem.
Check this:
http://html2canvas.hertzen.com/features
Unsupported CSS properties
These CSS properties are NOT currently supported
background-blend-mode
border-image
box-decoration-break
box-shadow
filter
font-variant-ligatures
mix-blend-mode
object-fit
repeating-linear-gradient()
writing-mode
zoom
I found out the solution to this. Putting a rectangle as border for each PDF page and also starting the second page, and other pages from a litte down, by making difference in the pageHeight.
You can try it like this:
html2canvas(myCanvas).then(function(canvas) {
var imgWidth = 210;
var pageHeight = 290;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm');
var position = 0;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var imgData = encodeURIComponent(pageData);
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
doc.setLineWidth(5);
doc.setDrawColor(255, 255, 255);
doc.rect(0, 0, 210, 295);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
doc.setLineWidth(5);
doc.setDrawColor(255, 255, 255);
doc.rect(0, 0, 210, 295);
heightLeft -= pageHeight;
}
doc.save('file.pdf');
});
Hope this will resolve your issue.
Related
After hours of work, trying to add a background to my svg i finally did it, but unfortunately if you go to resolution width= 767 and bellow the background image disappear. I really have no idea why is happening.
Here is the code i am using:
const width = 555
const height = 555
const canvas = d3.select(element)
.append('div')
.classed(css.svgContainer, true)
.append('svg')
.attr('preserveAspectRatio', 'xMinYMin meet')
.attr('viewBox', `0 0 ${width} ${height}`)
.attr('xmlns', 'http://www.w3.org/2000/svg')
.classed(css['svg-content-responsive'], true)
for (let i = 1; i < svg.length; i++) {
if (svg[i].type === 'path') {
const id = setItemId(i)
defs.append('svg:pattern')
.attr('id', id)
.attr('width', '275')
.attr('height', '281')
.attr('patternUnits', 'userSpaceOnUse')
.attr('patternTransform', 'matrix(1,0,0,1,0,0) translate(251.5,142.3)')
.append('svg:image')
.attr('xlink:href', imageSrc)
.attr('width', '275')
.attr('height', '281')
.attr('x', 0)
.attr('y', 0)
}
}
// Here is the css which makes the svg responsive
.svgContainer {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%; /* aspect ratio */
vertical-align: top;
overflow: hidden;
}
.svg-content-responsive {
display: inline-block;
position: absolute;
left: 0;
}
new to openlayers, i am currently trying to grab all tiles at certain zoom level within the view extent and add a feature/icon to each tile location, i can grab tile coords using
src.getSource().getTileGrid().forEachTileCoord
problem is it returns Z,X,Y tile coords (ie [16, 31689, 20858]) and i cant find anyway to either set icons location with these coords or convert them to lon/lat (eg 'EPSG:4326'[-5.928909184411161, 54.5921176536682]
iv tried
ol.proj.toLonLat
but it returns 0.00014373044545912343, 0.284665959233962, 20858.
as im new i may have something fundamentally wrong with my setup, or im completely missing something,thanks
To get actual coordinates you can use getTileCoordExtent / getCenter. This will get you the center coordinates for each tile.
By default the coordinate format is EPSG:3857 and no conversion should be needed to add a Feature.
const zDirection = 0;
const tileLayer = new ol.layer.Tile({
source: new ol.source.TileDebug({
zDirection: zDirection,
})
});
const style = new ol.style.Style({
image: new ol.style.Circle({
radius: 70,
fill: new ol.style.Fill({color: 'rgba(255, 0, 0, .2)'}),
}),
});
const layer = new ol.layer.Vector({
style: style,
});
const map = new ol.Map({
target: 'map',
view: new ol.View({
center: [0, 5000000],
zoom: 2,
}),
layers: [tileLayer, layer],
});
map.on('moveend', function () {
const view = map.getView();
const tileGrid = tileLayer.getSource().getTileGrid();
const extent = view.calculateExtent();
const zoom = tileGrid.getZForResolution(view.getResolution(), zDirection);
const features = [];
tileGrid.forEachTileCoord(extent, zoom, function (tileCoord) {
const center = ol.extent.getCenter(tileGrid.getTileCoordExtent(tileCoord));
features.push(new ol.Feature(new ol.geom.Point(center)));
});
layer.setSource(new ol.source.Vector({features: features}));
});
html, body {
padding: 0;
margin: 0;
}
body {
display: flex;
justify-content: stretch;
height: 100vh;
width: 100vw;
}
#map {
flex: 1;
}
<head>
<link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers#v6.14.1/src/ol/ol.css" rel="stylesheet"/>
</head>
<body>
<div id="map"></div>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.14.1/build/ol.js"></script>
</body>
import React, { Component } from 'react';
import * as am4core from "#amcharts/amcharts4/core";
// import * as am4charts from "#amcharts/amcharts4/charts";
import am4themes_animated from "#amcharts/amcharts4/themes/animated";
import * as am4maps from "#amcharts/amcharts4/maps";
import am4geodata_worldLow from "#amcharts/amcharts4-geodata/indiaLow";
import am4themes_frozen from "#amcharts/amcharts4/themes/frozen";
import './style.css'
am4core.useTheme(am4themes_frozen);
class WorldMap extends Component {
constructor(props){
super(props);
this.state = {
bubble:{}
}
}
componentDidMount() {
let chart = am4core.create("worldmap", am4maps.MapChart);
chart.geodata = am4geodata_worldLow;
chart.projection = new am4maps.projections.Miller();
let polygonSeries = chart.series.push(new am4maps.MapPolygonSeries());
polygonSeries.exclude = ["AQ"];
polygonSeries.useGeodata = true;
let polygonTemplate = polygonSeries.mapPolygons.template;
polygonTemplate.tooltipText = "{name}";
polygonTemplate.fill = chart.colors.getIndex(0).lighten(0.5);
let hs = polygonTemplate.states.create("hover");
hs.properties.fill = chart.colors.getIndex(0);
let imageSeries = chart.series.push(new am4maps.MapImageSeries());
imageSeries.mapImages.template.propertyFields.longitude = "longitude";
imageSeries.mapImages.template.propertyFields.latitude = "latitude";
imageSeries.data = [ {
"zoomLevel": 5,
"scale": 0.5,
"title": "Odisha",
"latitude": 20.29,
"longitude": 85.82,
}, {
"zoomLevel": 5,
"scale": 0.5,
"title": "Karnataka",
"latitude": 12.99,
"longitude": 77.71,
}, {
"zoomLevel": 5,
"scale": 0.5,
"title": "Andhra Pradesh",
"latitude": 14.99,
"longitude": 77.71,
}
];
chart.events.on( "mappositionchanged", updateCustomMarkers );
function updateCustomMarkers( event ) {
imageSeries.mapImages.each(function(image) {
if (!image.dummyData || !image.dummyData.externalElement) {
image.dummyData = {
externalElement: createCustomMarker(image)
};
}
let xy = chart.geoPointToSVG( { longitude: image.longitude, latitude: image.latitude } );
image.dummyData.externalElement.style.top = xy.y + 'px';
image.dummyData.externalElement.style.left = xy.x + 'px';
});
}
// this function creates and returns a new marker element
function createCustomMarker( image ) {
let chart = image.dataItem.component.chart;
// create holder
let holder = document.createElement( 'div' );
holder.className = 'map-marker';
holder.title = image.dataItem.dataContext.title;
holder.style.position = 'absolute';
// maybe add a link to it?
if ( undefined != image.url ) {
holder.onclick = function() {
window.location.href = image.url;
};
holder.className += ' map-clickable';
}
// create dot
let dot = document.createElement( 'div' );
dot.className = 'dot';
holder.appendChild( dot );
// create pulse
let pulse = document.createElement( 'div' );
pulse.className = 'pulse';
holder.appendChild( pulse );
// append the marker to the map container
chart.svgContainer.htmlElement.appendChild( holder );
return holder;
}
}
componentWillUnmount() {
if (this.chart) {
this.chart.dispose();
}
}
render() {
return (
<div id="worldmap" style={{ width: "100%", height: "500px" }}></div>
);
}
}
export default WorldMap;
Here i am using amcharts with React.
Please have a look into my screenshot.
I want exact like this and it is coming but ,
the marker those are coming yellow i wants to change some markers to red and green.
Is it possible to do that ??
I have shared the screenshot below please have a look.
i found it from amcharts map demos
So, React is irrelevant here. The demo you've copied is our "Custom HTML Elements as Map Markers" demo.
You've shared some of the JavaScript code, but since these markers are pure HTML, they are styled via CSS. Here's the CSS from the demo:
#chartdiv {
width: 100%;
height: 500px;
overflow: hidden;
}
.map-marker {
/* adjusting for the marker dimensions
so that it is centered on coordinates */
margin-left: -8px;
margin-top: -8px;
}
.map-marker.map-clickable {
cursor: pointer;
}
.pulse {
width: 10px;
height: 10px;
border: 5px solid #f7f14c;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
background-color: #716f42;
z-index: 10;
position: absolute;
}
.map-marker .dot {
border: 10px solid #fff601;
background: transparent;
-webkit-border-radius: 60px;
-moz-border-radius: 60px;
border-radius: 60px;
height: 50px;
width: 50px;
-webkit-animation: pulse 3s ease-out;
-moz-animation: pulse 3s ease-out;
animation: pulse 3s ease-out;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
position: absolute;
top: -20px;
left: -20px;
z-index: 1;
opacity: 0;
}
/* keyframe stuff here */
This is what's responsible for the yellow background color:
.pulse {
/*...*/
background-color: #716f42;
/*...*/
}
If you want to change background colors, it can be done via the background-color declaration on the .pulse div. You can add more CSS classes (after .pulse), e.g.
.pulse--red {
background-color: red;
}
.pulse--green {
background-color: green;
}
Or you can pass color keys in your data, e.g.
{
"zoomLevel": 5,
"scale": 0.5,
"title": "Karnataka",
"latitude": 12.99,
"longitude": 77.71,
"color": "red"
}
I am not sure what your logic would be for changing colors, but let's say we want to change every 2nd of 3 markers to red and every 3 of 3 markers to green, here's an updated createCustomMarker function that uses color from data and adds additional pulse--* classes:
// keep a counter for fuzzy color logic
var markers = 0;
// this function creates and returns a new marker element
function createCustomMarker( image ) {
var chart = image.dataItem.component.chart;
// create holder
var holder = document.createElement( 'div' );
holder.className = 'map-marker';
holder.title = image.dataItem.dataContext.title;
holder.style.position = 'absolute';
// maybe add a link to it?
if ( undefined != image.url ) {
holder.onclick = function() {
window.location.href = image.url;
};
holder.className += ' map-clickable';
}
// create dot
var dot = document.createElement( 'div' );
dot.className = 'dot';
holder.appendChild( dot );
// create pulse
var pulse = document.createElement( 'div' );
pulse.className = 'pulse';
// logic for switching colors
switch (markers) {
case 1:
pulse.className += " pulse--red";
++markers;
break;
case 2:
pulse.className += " pulse--green";
markers = 0;
break;
default:
++markers;
break;
}
// or apply color via data
var color = image.dataItem.dataContext.color;
if (color) {
// pulse.setAttribute('style', 'background-color: ' + color + ' !important');
// or
pulse.style.backgroundColor = color;
}
holder.appendChild( pulse );
// append the marker to the map container
chart.svgContainer.htmlElement.appendChild( holder );
return holder;
}
Here's a fork of our demo with the above:
https://codepen.io/team/amcharts/pen/6fad5b27c1456e6288032c5aaaae0c3e
I am working in angular application. i have a scenario here, when i am getting the titles from back-end the client requires that to be arranged around a oval (it contains some image)
and when the tiles length are odd then the firs element ( balance ) should be in the top. rest of the titles need to arrange the both side of the oval.
when i am getting the title length as even there is no need to keep the title in the top.
i tried some point. but i didn't get any valuable output.
my be the way i am doing (directive) is wrong? or this should be handle with some other way?
any one help me to find the mathematical logic here please?
click the bottom button to create random titles
Live Demo of my try
If I understand it correctly, you want something like this:
var radiusX = 250,
radiusY = 100,
texts = [],
oval = document.getElementById('oval'),
inp = document.querySelector('input');
document.querySelector('button').onclick = function() {
texts.push(inp.value);
inp.value = '';
while(oval.firstChild) oval.removeChild(oval.firstChild);
texts.forEach(function(text, i, arr){
var angle = Math.PI + (i*2 + 1 - arr.length%2) * Math.PI / arr.length;
var el = document.createElement('div');
el.style.top = radiusY + Math.cos(angle) * radiusY + 'px';
el.style.left = radiusX -Math.sin(angle) * radiusX + 'px';
el.textContent = text;
oval.appendChild(el);
});
};
#oval {
width: 500px;
height: 200px;
background: red;
border-radius: 100%;
margin: 0 auto;
position: relative;
margin-top: 20px;
}
#oval > div {
position: absolute;
line-height: 1.2;
height: 1.2em;
width: 3em;
margin-top: -.6em;
margin-left: -1.5em;
text-align: center;
}
<input id="text" placeholder="Write text..."/>
<button>Add text</button>
<div id="oval"></div>
Basically, divide 2 * Math.PI (360deg) into n equal angles, where n is the number of texts.
Then use Math.cos and Math.sin on that angle, and multiply it by the horizontal or vertical radius of the ellipse. That will give the coordinates relatively to the center of the ellipse.
Does anyone one have any ideo how to export EXT JS chart to PDF for printing? I could not find a solution online.
Here are the basic steps of how I did it.
Use Chart.Save method to obtain the SVG content of the chart you want to export.
Send the SVG content to the server
In the server side you can use rsvg-convert or a similar library to do PDF conversion.
// Insert this component into form items to print
{
xtype: 'button',
tooltip: getTranslate('{Print}'),
icon: getImg(16, 'printer'),
handler: function(comp) {
var obj = me.down('chart');
var el = obj.getEl();
me.print(el.getHTML(), getTranslate('{CashFlow}'));
}
}
// Print chart function
function printChart(html, title) {
var footerStyle = '#img {vertical-align:middle;} #footer {position:absolute; left: 0; right: 0; bottom: 0; height: 60px; margin-top: 40px; text-align: center; border:none; font-size: 10pt; border-top: 1px solid #000000;} ';
var noteStyle = '.note{display: block;' +
'padding: 10px;background-color: #F2F2F2;border-radius: 5px;box-shadow: 3px 3px 3px 0 rgba( 178, 178, 178, .5 );' +
'font-family: "Verdana", cursive, sans-serif;font-size:10px;color:#000;border:1px solid #000;' +
'outline:0;max-width: 300px;}';
var css = '<style>' + footerStyle + noteStyle + '</style>';
//var tela_impressao = window.open('about:blank');
var leftCenter = (screen.width-100) / 2;
var topCenter = 0; //screen.height / 2;
var tela_impressao = window.open('about:blank','_blank', 'toolbar=no,status=no,menubar=no,scrollbars=no,resizable=no,left=' + leftCenter + ', top=' + topCenter + ', width=100, height=10, visible=false', '');
var logoImg = '<img id="img" width="90px" height="45px" src="/servicos/interface/cognitus.png"/>';
var footer = '<div id="footer">' + logoImg + '<span></span></div>';
var xhtml = '<html><head><title>' + title + '</title>' + css + '</head><body>' + html + footer + '</body>';
tela_impressao.document.write(xhtml);
var myTimer;
var myFunc = function(){
tela_impressao.window.print(); // sem timer não carrega imagem para preview
tela_impressao.window.close();
timerStop(myTimer);
};
myTimer = timerRun(myFunc, 100);
}
// Executa uma função no intervalo de milesegundos
function timerRun(func, milliseconds) {
return setTimeout(func, milliseconds);
}
// Para a execução do time
function timerStop(timerVariable) {
clearTimeout(timerVariable);
}