Related
I have converted a pdf to image format using PDF.JS and rendered that to the canvas. While that process the rendered pdf image is showing blurred in the canvas.
I have no idea how to scale the image to some viewable format rather than being so blurred.
Image of the pdf in canvas:
Here in the image you can clearly see that the rendered image is not in readable format!
Here is the fiddle link: https://jsfiddle.net/kjxes63f/
var fabricCanvas;
fabricCanvas = new fabric.Canvas('firtcanvas');
document.querySelector("#pdf-upload").addEventListener("change", function (e) {
var file = e.target.files[0]
console.log("pdf evente");
console.log(e);
if (file.type != "application/pdf") {
console.error(file.name, "is not a pdf file.")
return
}
var fileReader = new FileReader();
fileReader.onload = function () {
var typedarray = new Uint8Array(this.result);
console.log("typedarray");
console.log(typedarray);
console.log("this.result");
console.log(this.result);
PDFJS.getDocument(typedarray).then(function (pdf) {
// you can now use *pdf* here
console.log("the pdf has ", pdf.numPages, "page(s).")
pdf.getPage(pdf.numPages).then(function (page) {
// you can now use *page* here
var viewport = page.getViewport(2.0);
var fabricCanvas = document.querySelector("#firtcanvas")
fabricCanvas.height = viewport.height;
fabricCanvas.width = viewport.width;
page.render({
canvasContext: fabricCanvas.getContext('2d'),
viewport: viewport
}).then(function () {
bg = fabricCanvas.toDataURL("image/png");
fabric.Image.fromURL(bg, function (img) {
img.scaleToHeight(800);
img.scaleToWidth(600);
console.log("img");
console.log(img);
console.log(bg);
var imgCanvas = img.set({ left: 0, top: 0, width: 150, height: 150 });
fabricCanvas.add(imgCanvas);
});
});
});
});
};
fileReader.readAsArrayBuffer(file);
});
Construction drawings are often wide-format and hard to read onscreen without zoom. As a work-around I'd suggest adding a zoom function to your canvas like below.
var canvas = new fabric.Canvas('pdfcanvas');
canvas.selection = false;
canvas.setHeight(450);
canvas.setWidth(636);
//zoom function
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var pointer = canvas.getPointer(opt.e);
var zoom = canvas.getZoom();
zoom = zoom - delta / 200;
if (zoom > 10) zoom = 10;
if (zoom < 1) {
zoom = 1;
canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
}
canvas.zoomToPoint({
'x': opt.e.offsetX,
'y': opt.e.offsetY
}, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
//pdf load
document.querySelector('#pdf-upload').addEventListener('change', function(e) {
var pageEl = document.getElementById('page-container');
var file = e.target.files[0];
if (file.type == 'application/pdf') {
var fileReader = new FileReader();
fileReader.onload = function() {
var typedarray = new Uint8Array(this.result);
PDFJS.getDocument(typedarray).then(function(pdf) {
//console.log('the pdf has ', pdf.numPages, 'page(s).');
pdf.getPage(pdf.numPages).then(function(pageEl) {
var viewport = pageEl.getViewport(2.0);
var canvasEl = document.querySelector('canvas');
canvasEl.height = viewport.height;
canvasEl.width = viewport.width;
pageEl.render({
'canvasContext': canvasEl.getContext('2d'),
'viewport': viewport
}).then(function() {
var bg = canvasEl.toDataURL('image/png');
fabric.Image.fromURL(bg, function(img) {
canvas.setBackgroundImage(img);
});
});
});
});
};
fileReader.readAsArrayBuffer(file);
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/1.8.349/pdf.min.js"></script>
<input id="pdf-upload" type="file">
<div id="page-container">
<canvas id="pdfcanvas"></canvas>
</div>
I would like to have nice preloader with percentage before game on, but nothing such appearing in spite of I am procceeding according to the Examples docs and api docs. It is simple HTML5 game based on phaser framework JS library. This is my code. What might be wrong? I am not digging in phaser library I have no time to repair broken libs all the time. I am just awaiting the things working out of the box somehow:
<html>
<head>
<meta charset="UTF-8">
<title>0002game</title>
<script src="phaser.min.js"></script>
<script>
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
var platforms;
var player;
var cursors;
var tehla1;
var tehla2;
var tehla3;
var tehla4;
var tehla5;
var poc=0;
var text=null;
var style=null;
var delta = 25;
var postext = 150;
var rychlost=1;
var text2;
var trafil1=false;var trafil2=false;var trafil3=false;var trafil4=false;var trafil5=false;
function preload() {
game.load.image('sky', 'assets/sky2.png');
game.load.image('wheelbarrow', 'assets/jet.png');
game.load.image('brick', 'assets/meteor.png');
game.load.image('ground', 'assets/ground.png');
game.load.audio('boden', ['assets/sound.wav']);
}
function loadStart() {
text2.setText("Loading...");
}
function loadComplete() {
text2.setText("Loading Completed.");
}
function fileComplete(progress, cacheKey, success, totalLoaded, totalFiles) {
text2.setText("File Complete: " + progress + "% - " + totalLoaded + " out of " + totalFiles);
}
function create() {
text2 = game.add.text(32, 32, 'Loading...', { fill: '#ffffff' });
music = game.add.audio('boden');
//music.play();
sounds = [music];
game.sound.setDecodedCallback(sounds, start, this);
game.world.setBounds(0, 0, 800, 600);
cursors = game.input.keyboard.createCursorKeys();
// We're going to be using physics, so enable the Arcade Physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
// A simple background for our game
game.add.sprite(0, 0, 'sky');
//var tehla = game.add.sprite(3, 3, 'brick');
tehla1 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla2 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla3 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla4 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla5 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
//game.add.sprite(0, 0, 'wheelbarrow');
// The platforms group contains the ground and the 2 ledges we can jump on
platforms = game.add.group();
// We will enable physics for any object that is created in this group
platforms.enableBody = true;
// Here we create the ground.
var ground = platforms.create(0, game.world.height - 64, 'ground');
// Scale it to fit the width of the game (the original sprite is 400x32 in size)
//ground.scale.setTo(2, 2);
// This stops it from falling away when you jump on it
ground.body.immovable = true;
// Now let's create two ledges
//var ledge = platforms.create(400, 400, 'ground');
//ledge.body.immovable = true;
//ledge = platforms.create(-150, 250, 'ground');
//ledge.body.immovable = true;
player = game.add.sprite(32, game.world.height - 120, 'wheelbarrow');
//player.body.bounce.y = 0.2;
//player.body.gravity.y = 300;
//player.body.collideWorldBounds = true;
style = { font: "25px Arial", fill: "#00ffff", align: "center" };
text = game.add.text(125, 25, "Lod zasiahli: ", style);
text.anchor.set(0.5);
game.load.onLoadStart.add(loadStart, this);
game.load.onFileComplete.add(fileComplete, this);
game.load.onLoadComplete.add(loadComplete, this);
}
function start() {
music.loopFull(1.0);
}
function cikoniec(){
if(poc==5){
alert('Uz ta zasiahlo 5 nepriatelov. Spustam hru znova!');
location.reload();
}
}
function update() {
//if(tehla1.y<game.height) game.add.tween(tehla1).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla1.y<game.height) tehla1.y+=rychlost;
if(tehla1.y>=game.height) {tehla1.y=game.rnd.integerInRange(20, 200);tehla1.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla1.y-player.y)<delta && Math.abs(tehla1.x-player.x)<delta && trafil1==false ){
poc=poc+1;
postext+=50;
tehla1.destroy();
text = game.add.text(postext, 35, "1", style);
trafil1 = true;
}
//if(tehla2.y<game.height) game.add.tween(tehla2).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla2.y<game.height) tehla2.y+=rychlost;
if(tehla2.y>=game.height) {tehla2.y=game.rnd.integerInRange(20, 200);tehla2.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla2.y-player.y)<delta && Math.abs(tehla2.x-player.x)<delta && trafil2==false ){
poc=poc+1;
postext+=50;
tehla2.destroy();
text = game.add.text(postext, 35, "2", style);
trafil2 = true;
}
//if(tehla3.y<game.height) game.add.tween(tehla3).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla3.y<game.height) tehla3.y+=rychlost;
if(tehla3.y>=game.height) {tehla3.y=game.rnd.integerInRange(20, 200);tehla3.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla3.y-player.y)<delta && Math.abs(tehla3.x-player.x)<delta && trafil3==false ){
poc=poc+1;
postext+=50;
tehla3.destroy();
text = game.add.text(postext, 35, "3", style);
trafil3 = true;
}
//if(tehla4.y<game.height) game.add.tween(tehla4).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla4.y<game.height) tehla4.y+=rychlost;
if(tehla4.y>=game.height) {tehla4.y=game.rnd.integerInRange(20, 200);tehla4.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla4.y-player.y)<delta && Math.abs(tehla4.x-player.x)<delta && trafil4==false ){
poc=poc+1;
postext+=50;
tehla4.destroy();
text = game.add.text(postext, 35, "4", style);
trafil4 = true;
}
//if(tehla5.y<game.height) game.add.tween(tehla5).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla5.y<game.height) tehla5.y+=rychlost;
if(tehla5.y>=game.height) {tehla5.y=game.rnd.integerInRange(20, 200);tehla5.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla5.y-player.y)<delta && Math.abs(tehla5.x-player.x)<delta && trafil5==false ){
poc=poc+1;
postext+=50;
tehla4.destroy();
text = game.add.text(postext, 35, "5", style);
trafil5 = true;
}
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
if(player.x>0) player.x -= 15;
cikoniec();
}
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
if(player.x<660) player.x += 15;
cikoniec();
}
game.physics.arcade.collide(player, platforms);
}
function render() {
game.debug.text('Hold left/right to move the player.');
}
</script>
</head>
<body>
<noscript>Sorry, your browser does not support JavaScript!</noscript>
</body>
</html>
Your best bet is to actually refactor this so that you have a more than one State in your game. Typically game templates will include a Boot and
some sort of Preload (or Preloader) state, as well as a menu (if needed) and the main game. Bold text should help with your search.
If you want to keep going down this path you can make a couple minor tweaks to your code. It will work, but it's not ideal. Again, take a look at States.
If you look at your code you'll notice that the functionality to actually hook up the loading text updates is at the bottom of your create. At this point the Phaser loader has already loaded the images.
If you look at the Load events example you'll see something kind of similar to what you have, but you'll notice that they're manually calling game.load.start().
Since you want the loading to start immediately, you need to get the load event binding done sooner.
Technically you can create whatever you want in the preload, but Phaser doesn't guarantee that you'll have any assets you're loading in. But this doesn't matter for a simple Phaser.Text object.
function preload() {
text2 = game.add.text(32, 32, 'Loading...', { fill: '#ffffff' });
game.load.onLoadStart.add(loadStart, this);
game.load.onFileComplete.add(fileComplete, this);
game.load.onLoadComplete.add(loadComplete, this);
game.load.image('sky', 'assets/sky2.png');
game.load.image('wheelbarrow', 'assets/jet.png');
game.load.image('brick', 'assets/meteor.png');
game.load.image('ground', 'assets/ground.png');
game.load.audio('boden', ['assets/sound.wav']);
}
So basically we add the text object and then hook into the loader, before loading the assets.
In your create function you can remove those four lines we added to preload.
You'll want to tweak it further, but again, I'd highly recommend looking at Phaser's State functionality. :) The first volume of Interphase has a pretty good overview of the functionality as well.
Solved, I did it this way:
<html>
<head>
<meta charset="UTF-8">
<title>0001game</title>
<style>
/* This only works with JavaScript,
if it's not present, don't show loader */
.no-js #loader { display: none; }
.js #loader { display: block; position: absolute; left: 100px; top: 0; }
</style>
<script src="jquery-1.5.2.min.js"></script>
<script src="modernizr.min.js"></script>
<script src="phaser.min.js"></script>
<script>
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
var platforms;
var player;
var cursors;
var tehla1;
var tehla2;
var tehla3;
var tehla4;
var tehla5;
var poc=0;
var text=null;
var style=null;
var delta = 25;
var postext = 150;
var rychlost=1;
var text2;
var trafil1=false;var trafil2=false;var trafil3=false;var trafil4=false;var trafil5=false;
function preload() {
game.load.image('sky', 'assets/sky.png');
game.load.image('wheelbarrow', 'assets/wheelbarrow.png');
game.load.image('brick', 'assets/brick.png');
game.load.image('ground', 'assets/ground.png');
game.load.audio('boden', ['assets/sound.wav']);
}
function create() {
text2 = game.add.text(32, 32, 'Loading...', { fill: '#ffffff' });
music = game.add.audio('boden');
//music.play();
sounds = [music];
game.sound.setDecodedCallback(sounds, start, this);
game.world.setBounds(0, 0, 800, 600);
cursors = game.input.keyboard.createCursorKeys();
// We're going to be using physics, so enable the Arcade Physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
// A simple background for our game
game.add.sprite(0, 0, 'sky');
//var tehla = game.add.sprite(3, 3, 'brick');
tehla1 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla2 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla3 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla4 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
tehla5 = game.add.sprite((Math.random() * 800), 0.2*game.world.randomY, 'brick');
//game.add.sprite(0, 0, 'wheelbarrow');
// The platforms group contains the ground and the 2 ledges we can jump on
platforms = game.add.group();
// We will enable physics for any object that is created in this group
platforms.enableBody = true;
// Here we create the ground.
var ground = platforms.create(0, game.world.height - 64, 'ground');
// Scale it to fit the width of the game (the original sprite is 400x32 in size)
//ground.scale.setTo(2, 2);
// This stops it from falling away when you jump on it
ground.body.immovable = true;
// Now let's create two ledges
//var ledge = platforms.create(400, 400, 'ground');
//ledge.body.immovable = true;
//ledge = platforms.create(-150, 250, 'ground');
//ledge.body.immovable = true;
player = game.add.sprite(32, game.world.height - 120, 'wheelbarrow');
//player.body.bounce.y = 0.2;
//player.body.gravity.y = 300;
//player.body.collideWorldBounds = true;
style = { font: "25px Arial", fill: "#ff0044", align: "center" };
text = game.add.text(125, 25, "Trafil roznych tehiel: ", style);
text.anchor.set(0.5);
game.load.onLoadStart.add(loadStart, this);
game.load.onFileComplete.add(fileComplete, this);
game.load.onLoadComplete.add(loadComplete, this);
}
function start() {
music.loopFull(1.0);
}
function cikoniec(){
if(poc==5){
alert('Uz si trafil/a vsetky tehly. Spustam hru znova!');
location.reload();
}
}
function update() {
//if(tehla1.y<game.height) game.add.tween(tehla1).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla1.y<game.height) tehla1.y+=rychlost;
if(tehla1.y>=game.height) {tehla1.y=game.rnd.integerInRange(20, 200);tehla1.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla1.y-player.y)<delta && Math.abs(tehla1.x-player.x)<delta && trafil1==false ){
poc=poc+1;
postext+=50;
tehla1.destroy();
text = game.add.text(postext, 35, "1", style);
trafil1 = true;
}
//if(tehla2.y<game.height) game.add.tween(tehla2).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla2.y<game.height) tehla2.y+=rychlost;
if(tehla2.y>=game.height) {tehla2.y=game.rnd.integerInRange(20, 200);tehla2.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla2.y-player.y)<delta && Math.abs(tehla2.x-player.x)<delta && trafil2==false ){
poc=poc+1;
postext+=50;
tehla2.destroy();
text = game.add.text(postext, 35, "2", style);
trafil2 = true;
}
//if(tehla3.y<game.height) game.add.tween(tehla3).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla3.y<game.height) tehla3.y+=rychlost;
if(tehla3.y>=game.height) {tehla3.y=game.rnd.integerInRange(20, 200);tehla3.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla3.y-player.y)<delta && Math.abs(tehla3.x-player.x)<delta && trafil3==false ){
poc=poc+1;
postext+=50;
tehla3.destroy();
text = game.add.text(postext, 35, "3", style);
trafil3 = true;
}
//if(tehla4.y<game.height) game.add.tween(tehla4).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla4.y<game.height) tehla4.y+=rychlost;
if(tehla4.y>=game.height) {tehla4.y=game.rnd.integerInRange(20, 200);tehla4.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla4.y-player.y)<delta && Math.abs(tehla4.x-player.x)<delta && trafil4==false ){
poc=poc+1;
postext+=50;
tehla4.destroy();
text = game.add.text(postext, 35, "4", style);
trafil4 = true;
}
//if(tehla5.y<game.height) game.add.tween(tehla5).to({ y: game.height*1.1 }, 1000, Phaser.Easing.Linear.None, true);
if(tehla5.y<game.height) tehla5.y+=rychlost;
if(tehla5.y>=game.height) {tehla5.y=game.rnd.integerInRange(20, 200);tehla5.x=game.rnd.integerInRange(20, 500);}
if(Math.abs(tehla5.y-player.y)<delta && Math.abs(tehla5.x-player.x)<delta && trafil5==false ){
poc=poc+1;
postext+=50;
tehla5.destroy();
text = game.add.text(postext, 35, "5", style);
trafil5 = true;
}
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
if(player.x>0) player.x -= 15;
cikoniec();
}
else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
{
if(player.x<660) player.x += 15;
cikoniec();
}
game.physics.arcade.collide(player, platforms);
}
function render() {
game.debug.text('Hold left/right to move the player.');
}
</script>
<script>
// Wait for window load
$(window).load(function() {
// Animate loader off screen
$("#loader").animate({
top: -200
}, 1500);
});
</script>
</head>
<body>
<img src="assets/loader.gif" id="loader">
<noscript>Sorry, your browser does not support JavaScript!</noscript>
</body>
</html>
This morning I just started getting a google maps script error.
Line: 0
Char: 0
Error: Script Error
Code: 0
URL:
I reverted all my code changes back to an earlier version but it still persists.
I will include the script below but I must mention that this runs in a Delphi TWebBrowser that interfaces IE.
I can run my program, interact with the Page and then let it sit idle. After 20 seconds or so, without any user interaction, I get the persistent error above. When I close the Error Message box, it immediately opens with the same message.
I have been working this project for months and now this started. I have rolled back several versions but it still persists.
Where do I start looking?
<html>
<head>
<title>Find your Qtr minute locator</title>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?api=AIzaSyAa7YZpvi09ig92s_BLP2H3QVLTmoqdcQQ&v=3.exp&libraries=geometry&sensor=false"></script>
</head>
<body><!-- Declare the div, make it take up the full document body -->
<div id="map-canvas" style="HEIGHT: 100%; WIDTH: 100%"></div>
<script type="text/javascript">
var map;
var idx = 0;
var qtrArray = [];
var userGridArray = [];
var Startlatlng = "";
var llOffset = 0.00416666666667;
var babyOffset = (llOffset/2); // offsets gridSelector 1/2 qtr min
var drawGridSelectBox = false;
var findNeighbor = false;
var firstRun = true;
var drawGridBox = false;
var deSelectOn = false;
var GridSelect = false;
var gridOverBox = new google.maps.Polygon();
var gridSelectBox = new google.maps.Polygon();
var gridline;
var polylinesquare;
var latPolylines = [];
var lngPolylines = [];
var lngLabels = [];
var otherColor = "#128A00";
var bounds = new google.maps.LatLngBounds();
function initialize() {
map = new google.maps.Map(document.getElementById("map-canvas"), {
center: new google.maps.LatLng(34.0, -84.0),
zoom: 14,
streetViewControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true
});
google.maps.event.addListener(map, "click", function (event) {
if (!google.maps.geometry.poly.containsLocation(event.latLng, gridSelectBox)) {
map.setZoom(14);
if (findNeighbor)
MarkArea(event.latLng.lat(), event.latLng.lng());
if (drawGridSelectBox) {
createGridSelectBox(event.latLng);
GridSelect = !firstRun;
if (!GridSelect) {
ClearGrid()
}
}
for(var xx=0;xx<latPolylines.length;++xx){
for(var yy=0;yy<lngPolylines.length-1;++yy){
var latLng=new google.maps.LatLng(latPolylines[xx].getPath().getAt(0).lat(),
lngPolylines[yy].getPath().getAt(0).lng());
if ((google.maps.geometry.poly.containsLocation(latLng, gridSelectBox))&&(!firstRun))
{
drawGridBox = true;
createGridBox(latLng);
}
}
}
firstRun = false;
map.panTo(event.latLng);
drawGridBox = false;
}});
DrawGridOn();
google.maps.event.addListener(map, "idle", function () {
createGridLines(map.getBounds());
});
} // initialize
google.maps.event.addDomListener(window, "load", initialize);
function createGridLines(bounds) {
for (var i = 0; i < latPolylines.length; i++) {
latPolylines[i].setMap(null);
}
latPolylines = [];
for (var j = 0; j < lngPolylines.length; j++) {
lngPolylines[j].setMap(null);
}
lngPolylines = [];
for (var k = 0; k < lngLabels.length; k++) {
lngLabels[k].setMap(null);
}
lngLabels = [];
if (map.getZoom() < 10) return;
var north = bounds.getNorthEast().lat();
var east = bounds.getNorthEast().lng();
var south = bounds.getSouthWest().lat();
var west = bounds.getSouthWest().lng();
// define the size of the grid
var topLat = Math.ceil(north / llOffset) * llOffset;
var rightLong = Math.ceil(east / llOffset) * llOffset;
var bottomLat = Math.floor(south / llOffset) * llOffset;
var leftLong = Math.floor(west / llOffset) * llOffset;
var qtrNELatLngCode = ddToQM(topLat, rightLong);
var qtrNorth = qtrNELatLngCode.substring(0, 5);
var qtrEast = qtrNELatLngCode.substring(5, 12);
var qtrSWLatLngCode = ddToQM(bottomLat, leftLong);
var qtrSouth = qtrSWLatLngCode.substring(0, 5);
var qtrWest = qtrSWLatLngCode.substring(5, 12);
for (var latitude = bottomLat; latitude <= topLat; latitude += llOffset) latPolylines.push(new google.maps.Polyline({
path: [
new google.maps.LatLng(latitude, leftLong), new google.maps.LatLng(latitude, rightLong)],
map: map,
geodesic: true,
strokeColor: "#0000FF",
strokeOpacity: 0.1,
strokeWeight: 1
}));
for (var longitude = leftLong; longitude <= rightLong; longitude += llOffset) lngPolylines.push(new google.maps.Polyline({
path: [
new google.maps.LatLng(topLat, longitude), new google.maps.LatLng(bottomLat, longitude)],
map: map,
geodesic: true,
strokeColor: "#0000FF",
strokeOpacity: 0.1,
strokeWeight: 1
}));
if (map.getZoom() < 15) {
for (var l = 0; l < lngLabels.length; l++) {
lngLabels[l].setMap(null);
}
lngLabels = [];
return;
} // set lngLabels to null
for(var x=0;x<latPolylines.length;++x){
for(var y=0;y<lngPolylines.length-1;++y){
var latLng=new google.maps.LatLng(latPolylines[x].getPath().getAt(0).lat(),
lngPolylines[y].getPath().getAt(0).lng());
var qtrLatLng = ddToQM(latLng.lat(), latLng.lng());
lngLabels.push(new google.maps.Marker({
map:map,
position:latLng,
icon:{ url:"https://chart.googleapis.com/chart?"
+"chst=d_bubble_text_small&chld=bb|"
+ qtrLatLng
+"|FFFFFF|000000",
anchor:new google.maps.Point(0,42)
}
}));
}
}
external.ShowQtrMinBounds(qtrNorth, qtrSouth, qtrEast, qtrWest);
} // end createGridLines
function createGridSelectBox(point) {
// Square limits
var smPoint = point;
var bottomLeftLat = (Math.floor(point.lat() / llOffset) * llOffset) - babyOffset;
var bottomLeftLong = (Math.floor(point.lng() / llOffset) * llOffset) - babyOffset;
var gridLineSquare = [
new google.maps.LatLng(bottomLeftLat, bottomLeftLong), //lwr left
new google.maps.LatLng(bottomLeftLat, bottomLeftLong + llOffset), //lwr right
new google.maps.LatLng(bottomLeftLat + llOffset, bottomLeftLong + llOffset), //upr right
new google.maps.LatLng(bottomLeftLat + llOffset, bottomLeftLong)]; //upr left
//auto-complete to lwr left
if (drawGridSelectBox == true) {
gridSelectBox = new google.maps.Polygon({
path: gridLineSquare,
draggable:true,
geodesic:true,
editable :true,
fillColor: "#FF0000",
fillOpacity: 0.35,
strokeColor: "#CC0099",
strokeOpacity: 0.1,
strokeWeight: 1
});
gridSelectBox.setMap(map);
drawGridSelectBox = false;
}
}
function MarkArea(Lat, Lng) {
var latLng = new google.maps.LatLng(Lat,Lng);
drawUserGrids(latLng);
}
function SaveQtrMin(){
for (var m in qtrArray) {
external.SaveQtrMinutes(qtrArray[m].qtrMinute);
}
}
function DrawGridOn() { //creates GridSelectBox
addGridOn = false;
drawGridSelectBox = true;
firstRun = true;
}
function DrawGridOff() {
gridSelectBox.setMap(null);
drawGridSelectBox = false;
}
function GotoLatLng(Lat, Lng) {
var latlng = new google.maps.LatLng(Lat,Lng);
map.setCenter(latlng);
}
function DeSelectOn(){
deSelectOn = true;
addGridOn = false;
}
function DeSelectOff(){ // Allows removing 1 QtrMin
deSelectOn = false;
}
function AddGridOn(){ // Allows adding 1 QtrMin
addGridOn = true;
deSelectOn = false;
}
function AddGridOff(){
addGridOn = false;
}
function ClearGrid() {
if (qtrArray) {
for (var i in qtrArray) {
qtrArray[i].setMap(null);
}
}
qtrArray=[];
idx = 0;
}
function ClearUserGrid() {
if (userGridArray) {
for (var i in userGridArray) {
userGridArray[i].setMap(null);
}
}
userGridArray=[];
}
function drawUserGrids(point) {
// Square limits
var bottomLeftLat = (Math.floor(point.lat() / llOffset) * llOffset);
var bottomLeftLong = (Math.floor(point.lng() / llOffset) * llOffset);
var gridLineSquare = [
new google.maps.LatLng(bottomLeftLat, bottomLeftLong), //lwr left
new google.maps.LatLng(bottomLeftLat, (bottomLeftLong + llOffset)), //lwr right
new google.maps.LatLng((bottomLeftLat + llOffset), (bottomLeftLong + llOffset)), //upr right
new google.maps.LatLng((bottomLeftLat + llOffset), bottomLeftLong)]; //upr left
drawGridBox = true;
if (drawGridBox == true) {
gridUserArea = new google.maps.Polygon({
path: gridLineSquare,
draggable:false,
geodesic:true,
editable :false,
fillColor:otherColor,
fillOpacity: 0.35,
strokeColor: "#CC0099",
strokeOpacity: 0.1,
strokeWeight: 1
});
gridUserArea.setMap(map);
userGridArray.push(gridUserArea);
}
}
function createGridBox(point) {
// Square limits
var arrayIdx = 0;
var addListenersOnPolygon = function(polygon) {
google.maps.event.addListener(polygon, 'click', function (event) {
if (deSelectOn==true) {
arrayIdx = qtrArray.indexOf(polygon);
qtrArray.splice(arrayIdx,1);
polygon.setMap(null);
}
});
};
var smPoint = point;
var bottomLeftLat = (Math.floor(point.lat() / llOffset) * llOffset);
var bottomLeftLong = (Math.floor(point.lng() / llOffset) * llOffset);
var gridLineSquare = [
new google.maps.LatLng(bottomLeftLat, bottomLeftLong), //lwr left
new google.maps.LatLng(bottomLeftLat, (bottomLeftLong + llOffset)), //lwr right
new google.maps.LatLng((bottomLeftLat + llOffset), (bottomLeftLong + llOffset)), //upr right
new google.maps.LatLng((bottomLeftLat + llOffset), bottomLeftLong)]; //upr left
drawGridBox = true;
if (drawGridBox == true) {
gridOverBox = new google.maps.Polygon({
path: gridLineSquare,
draggable:false,
geodesic:true,
editable :false,
fillColor: "#EAED00",
fillOpacity: 0.35,
strokeColor: "#CC0099",
strokeOpacity: 0.1,
strokeWeight: 1,
qtrMinute : ddToQM(bottomLeftLat, bottomLeftLong),
indexID : ++idx
});
gridOverBox.setMap(map);
addListenersOnPolygon(gridOverBox);
qtrArray.push(gridOverBox);
}
}
function ddToQM(alat, alng) {
var latResult, lngResult, dmsResult;
alat = parseFloat(alat);
alng = parseFloat(alng);
latResult = "";
lngResult = "";
latResult += getDms(alat);
lngResult += getDms(alng);
dmsResult = latResult + lngResult;
// Return the resultant string.
return dmsResult;
}
function toggleGridSelection(){
GridSelect = true;//(!!GridSelect);
}
function findNeighborOn(){
findNeighbor = true;
otherColor = randColor();
}
function findNeighborOff(){
findNeighbor = false;
otherColor = "#128A00";
}
function randColor() {
var i;
var colorArray = ["#B2A209","#A4A07B","#B02600","#6CA200","#BC0072","#B1ADFF","#16CADB","#A1FFD1","#9999CC","#EEFF7C"];
i = Math.floor((Math.random() *10)+1);
return colorArray[i];
}
function getDms(val) {
// Required variables
var valDeg, valMin, valSec, interimResult;
var qtrMin;
val = Math.abs(val);
// ---- Degrees ----
valDeg = Math.floor(val);
valMin = Math.floor((val - valDeg) * 60);
valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000) / 1000;
if (valSec == 60){
valMin +=1;
valSec = 0;
}
if (valMin == 60){
valMin +=1;
valSec = 0;
}
interimResult = valDeg+"";
if (valMin<10){
valMin = "0"+valMin;
}
interimResult += valMin + "";
switch(valSec){
case 0 : qtrMin = "A";
break;
case 15 : qtrMin = "B";
break;
case 30 : qtrMin = "C";
break;
case 45 : qtrMin = "D";
break;
}
interimResult += qtrMin;
return interimResult;
}
</script>
</body>
</html>
Adding the following meta tag in a header section solved this issue for me.
<meta http-equiv="X-UA-Compatible" content="IE=edge">
The X-UA-Compatible meta tag allows web authors to choose what
version of Internet Explorer the page should be rendered as.
Edge mode tells Internet Explorer to display content in the highest mode
available.
I also changed this tag. then work it well. thanks
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
It works both ver 3.22 & 3.23.
This onion.js script error has returned, the v=3.22 no longer fixes the issue. It turns out that the problem is an issue with IE and onios.js. Embedding a web browser by default used IE7 standard and that’s the problem my fix was an addition to the registry as follows:-
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
"yourApp.exe"=dword:00002EDF
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
"yourApp.exe"=dword:00002EDF
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
"yourApp.exe"=dword:00002EDF
Google launched a new release version 3.24 on May 24, 2016.
According to the versioning model, there are only three versions: frozen, release and experimental.
https://developers.google.com/maps/documentation/javascript/versions
Version 3.22 is retired and cannot be accessed anymore.
The new version supports only IE10 and IE11, the compatibility mode is unsupported.
https://developers.google.com/maps/documentation/javascript/browsersupport
WebBrowser control can default to an IE 7 rendering mode:
https://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version
You should force the control to a newer IE version
http://www.codeproject.com/Articles/793687/Configuring-the-emulation-mode-of-an-Internet-Expl
Use latest version of Internet Explorer in the webbrowser control
Additionally, you can add the meta tag in your html
It looks like the new version of Maps JavaScript API relies on a global JSON object which is not available in IE7. So, alternatively you can try to polyfill JSON:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
I was having the same error.
I've just found a solution that worked for me.
I just added "&v=3.22" in the url of Google Maps.
Like this:
http://maps.google.com/maps/api/js?sensor=true&v=3.22
I was having a similar problem and the provided solution didn't work for me. I was getting the error in Delphi inside the TWebBrowser control also with the meta tag.
I figured out the problem.
Onion.js fires the error, because it calls JSON.parse.
JSON Parse isn't supported by the web browser control. You can test this by adding this to your JavaScript (already quoted for Delphi):
'var code = ''"\u2028\u2029"''; JSON.parse(code); ' +
Every browser should execute
var code = '"\u2028\u2029"';
JSON.parse(code);
When executed in Delphi it fires an error instantly.
You can avoid the whole thing with a JSON3 polyfill (already quoted for Delphi):
'<script src="https://cdn.jsdelivr.net/json3/3.3.2/json3.js"></script>' +
Then JSON will be defined and work as expected, resolving the problem.
I have a requirement to render a set of time series data of contiguous blocks.
I need to describe a series of bars which could span many hours, or just minutes, with their own Y value.
I'm not sure if ChartJS is what I should be using for this, but I have looked at extending the Bar type, but it seems very hard coded for each bar to be the same width. The Scale Class internally is used for labels, chart width etc, not just the bars themselves.
I am trying to achieve something like this that works in Excel: http://peltiertech.com/variable-width-column-charts/
Has anyone else had to come up with something similar?
I found I needed to do this and the answer by #potatopeelings was great, but out of date for version 2 of Chartjs. I did something similar by creating my own controller/chart type via extending bar:
//controller.barw.js
module.exports = function(Chart) {
var helpers = Chart.helpers;
Chart.defaults.barw = {
hover: {
mode: 'label'
},
scales: {
xAxes: [{
type: 'category',
// Specific to Bar Controller
categoryPercentage: 0.8,
barPercentage: 0.9,
// grid line settings
gridLines: {
offsetGridLines: true
}
}],
yAxes: [{
type: 'linear'
}]
}
};
Chart.controllers.barw = Chart.controllers.bar.extend({
/**
* #private
*/
getRuler: function() {
var me = this;
var scale = me.getIndexScale();
var options = scale.options;
var stackCount = me.getStackCount();
var fullSize = scale.isHorizontal()? scale.width : scale.height;
var tickSize = fullSize / scale.ticks.length;
var categorySize = tickSize * options.categoryPercentage;
var fullBarSize = categorySize / stackCount;
var barSize = fullBarSize * options.barPercentage;
barSize = Math.min(
helpers.getValueOrDefault(options.barThickness, barSize),
helpers.getValueOrDefault(options.maxBarThickness, Infinity));
return {
fullSize: fullSize,
stackCount: stackCount,
tickSize: tickSize,
categorySize: categorySize,
categorySpacing: tickSize - categorySize,
fullBarSize: fullBarSize,
barSize: barSize,
barSpacing: fullBarSize - barSize,
scale: scale
};
},
/**
* #private
*/
calculateBarIndexPixels: function(datasetIndex, index, ruler) {
var me = this;
var scale = ruler.scale;
var options = scale.options;
var isCombo = me.chart.isCombo;
var stackIndex = me.getStackIndex(datasetIndex);
var base = scale.getPixelForValue(null, index, datasetIndex, isCombo);
var size = ruler.barSize;
var dataset = me.chart.data.datasets[datasetIndex];
if(dataset.weights) {
var total = dataset.weights.reduce((m, x) => m + x, 0);
var perc = dataset.weights[index] / total;
var offset = 0;
for(var i = 0; i < index; i++) {
offset += dataset.weights[i] / total;
}
var pixelOffset = Math.round(ruler.fullSize * offset);
var base = scale.isHorizontal() ? scale.left : scale.top;
base += pixelOffset;
size = Math.round(ruler.fullSize * perc);
size -= ruler.categorySpacing;
size -= ruler.barSpacing;
}
base -= isCombo? ruler.tickSize / 2 : 0;
base += ruler.fullBarSize * stackIndex;
base += ruler.categorySpacing / 2;
base += ruler.barSpacing / 2;
return {
size: size,
base: base,
head: base + size,
center: base + size / 2
};
},
});
};
Then you need to add it to your chartjs instance like this:
import Chart from 'chart.js'
import barw from 'controller.barw'
barw(Chart); //add plugin to chartjs
and finally, similar to the other answer, the weights of the bar widths need to be added to the data set:
var data = {
labels: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.7)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 30, 56, 65, 40],
weights: [1, 0.9, 1, 2, 1, 4, 0.3]
},
]
};
This will hopefully get someone onto the right track. What I have certainly isn't perfect, but if you make sure you have the right number of weight to data points, you should be right.
Best of luck.
This is based on the #Shane's code, I just posted to help, since is a common question.
calculateBarIndexPixels: function (datasetIndex, index, ruler) {
const options = ruler.scale.options;
const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options) : computeFitCategoryTraits(index, ruler, options);
const barSize = range.chunk;
const stackIndex = this.getStackIndex(datasetIndex, this.getMeta().stack);
let center = range.start + range.chunk * stackIndex + range.chunk / 2;
let size = range.chunk * range.ratio;
let start = range.start;
const dataset = this.chart.data.datasets[datasetIndex];
if (dataset.weights) {
//the max weight should be one
size = barSize * dataset.weights[index];
const meta = this.chart.controller.getDatasetMeta(0);
const lastModel = index > 0 ? meta.data[index - 1]._model : null;
//last column takes the full bar
if (lastModel) {
//start could be last center plus half of last column width
start = lastModel.x + lastModel.width / 2;
}
center = start + size * stackIndex + size / 2;
}
return {
size: size,
base: center - size / 2,
head: center + size / 2,
center: center
};
}
For Chart.js you can create a new extension based on the bar class to do this. It's a bit involved though - however most of it is a copy paste of the bar type library code
Chart.types.Bar.extend({
name: "BarAlt",
// all blocks that don't have a comment are a direct copy paste of the Chart.js library code
initialize: function (data) {
// the sum of all widths
var widthSum = data.datasets[0].data2.reduce(function (a, b) { return a + b }, 0);
// cumulative sum of all preceding widths
var cumulativeSum = [ 0 ];
data.datasets[0].data2.forEach(function (e, i, arr) {
cumulativeSum.push(cumulativeSum[i] + e);
})
var options = this.options;
// completely rewrite this class to calculate the x position and bar width's based on data2
this.ScaleClass = Chart.Scale.extend({
offsetGridLines: true,
calculateBarX: function (barIndex) {
var xSpan = this.width - this.xScalePaddingLeft;
var x = this.xScalePaddingLeft + (cumulativeSum[barIndex] / widthSum * xSpan) - this.calculateBarWidth(barIndex) / 2;
return x + this.calculateBarWidth(barIndex);
},
calculateBarWidth: function (index) {
var xSpan = this.width - this.xScalePaddingLeft;
return (xSpan * data.datasets[0].data2[index] / widthSum);
}
});
this.datasets = [];
if (this.options.showTooltips) {
Chart.helpers.bindEvents(this, this.options.tooltipEvents, function (evt) {
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
this.eachBars(function (bar) {
bar.restore(['fillColor', 'strokeColor']);
});
Chart.helpers.each(activeBars, function (activeBar) {
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
});
this.showTooltip(activeBars);
});
}
this.BarClass = Chart.Rectangle.extend({
strokeWidth: this.options.barStrokeWidth,
showStroke: this.options.barShowStroke,
ctx: this.chart.ctx
});
Chart.helpers.each(data.datasets, function (dataset, datasetIndex) {
var datasetObject = {
label: dataset.label || null,
fillColor: dataset.fillColor,
strokeColor: dataset.strokeColor,
bars: []
};
this.datasets.push(datasetObject);
Chart.helpers.each(dataset.data, function (dataPoint, index) {
datasetObject.bars.push(new this.BarClass({
value: dataPoint,
label: data.labels[index],
datasetLabel: dataset.label,
strokeColor: dataset.strokeColor,
fillColor: dataset.fillColor,
highlightFill: dataset.highlightFill || dataset.fillColor,
highlightStroke: dataset.highlightStroke || dataset.strokeColor
}));
}, this);
}, this);
this.buildScale(data.labels);
// remove the labels - they won't be positioned correctly anyway
this.scale.xLabels.forEach(function (e, i, arr) {
arr[i] = '';
})
this.BarClass.prototype.base = this.scale.endPoint;
this.eachBars(function (bar, index, datasetIndex) {
// change the way the x and width functions are called
Chart.helpers.extend(bar, {
width: this.scale.calculateBarWidth(index),
x: this.scale.calculateBarX(index),
y: this.scale.endPoint
});
bar.save();
}, this);
this.render();
},
draw: function (ease) {
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
this.scale.draw(1);
Chart.helpers.each(this.datasets, function (dataset, datasetIndex) {
Chart.helpers.each(dataset.bars, function (bar, index) {
if (bar.hasValue()) {
bar.base = this.scale.endPoint;
// change the way the x and width functions are called
bar.transition({
x: this.scale.calculateBarX(index),
y: this.scale.calculateY(bar.value),
width: this.scale.calculateBarWidth(index)
}, easingDecimal).draw();
}
}, this);
}, this);
}
});
You pass in the widths like below
var data = {
labels: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.7)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 30, 56, 65, 40],
data2: [10, 20, 30, 20, 10, 40, 10]
},
]
};
and you call it like so
var ctx = document.getElementById('canvas').getContext('2d');
var myLineChart = new Chart(ctx).BarAlt(data);
Fiddle - http://jsfiddle.net/moye0cp4/
How to set a full length background color for each bar in chartjs bar
pls refer below link i need same output
https://drive.google.com/file/d/0B4X0e4vwH_UPVGxWN2NBdURyZ0E/view?usp=sharing
You can adapt the other answer to show the background only for the bars - note that in this case you'll need the bars collection
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function (data) {
var self = this;
var originalBuildScale = self.buildScale;
self.buildScale = function () {
originalBuildScale.apply(this, arguments);
var ctx = self.chart.ctx;
var scale = self.scale;
var originalScaleDraw = self.scale.draw;
var barAreaWidth = scale.calculateX(1) - scale.calculateX(0);
var barAreaHeight = scale.endPoint - scale.startPoint;
self.scale.draw = function () {
originalScaleDraw.call(this, arguments);
ctx.fillStyle = data.barBackground;
self.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
ctx.fillRect(
bar.x - bar.width / 2,
scale.startPoint,
bar.width,
barAreaHeight);
})
})
ctx.fill();
}
}
Chart.types.Bar.prototype.initialize.apply(this, arguments);
}
});
with the chart data like so
var data = {
barBackground: "rgba(221, 224, 229, 1)",
...
and the call like so (as before)
var ctx = document.getElementById("chart").getContext("2d");
var myBarChart = new Chart(ctx).BarAlt(data, {
barValueSpacing: 15,
});
Fiddle - http://jsfiddle.net/ayy2vxsj/
You could extend the bar chart and override the scale draw event to shade the background, like so
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function (data) {
var self = this;
var originalBuildScale = self.buildScale;
self.buildScale = function () {
originalBuildScale.apply(this, arguments);
var ctx = self.chart.ctx;
var scale = self.scale;
var originalScaleDraw = self.scale.draw;
var barAreaWidth = scale.calculateX(1) - scale.calculateX(0);
var barAreaHeight = scale.endPoint - scale.startPoint;
self.scale.draw = function () {
originalScaleDraw.call(this, arguments);
scale.xLabels.forEach(function (xLabel, i) {
ctx.fillStyle = data.labelBackgrounds[i];
ctx.fillRect(
scale.calculateX(i - (scale.offsetGridLines ? 0.5 : 0)),
scale.startPoint,
barAreaWidth,
barAreaHeight);
ctx.fill();
})
}
}
Chart.types.Bar.prototype.initialize.apply(this, arguments);
}
});
with the chart data like so
var data = {
labelBackgrounds: ["rgba(120,220,220,0.2)", "rgba(220,120,220,0.2)", "rgba(220,220,120,0.2)", "rgba(120,120,220,0.2)", "rgba(120,220,120,0.2)", "rgba(220,120,120,0.2)", "rgba(120,120,120,0.2)"],
labels: ...
Note - if you just want to color the bars, I believe there was already a question on SO for the same.
Fiddle - http://jsfiddle.net/x73rhq2y/