Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add the ability to load images using ajax #51

Open
wants to merge 10 commits into
base: gh-pages
Choose a base branch
from
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
var snapshot = document.getElementById('snapshot');
var map = L.mapbox.map('map', 'mapbox.streets')
.setView([38.88995, -77.00906], 15);

L.marker([38.88995, -77.00906]).addTo(map);
document.getElementById('snap').addEventListener('click', function() {
leafletImage(map, doImage);
});
Expand Down
80 changes: 73 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
var queue = require('./queue');

// leaflet-image
module.exports = function leafletImage(map, callback) {
module.exports = function leafletImage(map, callback, useAjax) {

var dimensions = map.getSize(),
layerQueue = new queue(1);
layerQueue = new queue(1),
imageCache = {};

var canvas = document.createElement('canvas');
canvas.width = dimensions.x;
Expand All @@ -28,17 +29,19 @@ module.exports = function leafletImage(map, callback) {
} else if (map._panes && map._panes.overlayPane.firstChild) {
layerQueue.defer(handlePathRoot, map._panes.overlayPane.firstChild);
}
map.eachLayer(drawMarkerLayer);
map.eachLayer(drawLayer);
layerQueue.awaitAll(layersDone);

function drawTileLayer(l) {
if (l instanceof L.TileLayer) layerQueue.defer(handleTileLayer, l);
else if (l._heat) layerQueue.defer(handlePathRoot, l._canvas);
}

function drawMarkerLayer(l) {
function drawLayer(l) {
if (l instanceof L.Marker && l.options.icon instanceof L.Icon) {
layerQueue.defer(handleMarkerLayer, l);
} else if (typeof l.redraw === 'function' && l.canvas) {
layerQueue.defer(handleCanvasLayer, l);
}
}

Expand All @@ -53,6 +56,11 @@ module.exports = function leafletImage(map, callback) {
ctx.drawImage(layer.canvas, 0, 0);
}
});
layers.forEach(function (layer) {
if (layer && layer.img && !layer.canvas) {
ctx.drawImage(layer.img, 0, 0);
}
});
done();
}

Expand Down Expand Up @@ -185,12 +193,14 @@ module.exports = function leafletImage(map, callback) {
minPoint = new L.Point(pixelBounds.min.x, pixelBounds.min.y),
pixelPoint = map.project(marker.getLatLng()),
isBase64 = /^data\:/.test(marker._icon.src),
cache = imageCache[marker._icon.src],
url = isBase64 ? marker._icon.src : addCacheString(marker._icon.src),
im = new Image(),
options = marker.options.icon.options,
size = options.iconSize,
pos = pixelPoint.subtract(minPoint),
anchor = L.point(options.iconAnchor || size && size.divideBy(2, true));
anchor = L.point(options.iconAnchor || size && size.divideBy(2, true)),
loaded = false;

if (size instanceof L.Point) size = [size.x, size.y];

Expand All @@ -202,18 +212,74 @@ module.exports = function leafletImage(map, callback) {
im.crossOrigin = '';

im.onload = function() {
if (loaded) return;
loaded = true;
ctx.drawImage(this, x, y, size[0], size[1]);
callback(null, {
canvas: canvas
});
};

im.src = url;
if (useAjax && !isBase64) {
if (cache === undefined) {
getBase64(url, function (data) {
im.src = imageCache[marker._icon.src] = 'data: image/png;base64, ' + data;
if (!loaded) {
setTimeout(function() {
im.onload();
},0);
}
});
} else {
im.src = cache;
if (!loaded) {
setTimeout(function() {
im.onload();
},0);
}
}
} else {
im.src = url;

if (isBase64) im.onload();
if (isBase64 && !loaded) {
setTimeout(function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there a settimeout here, and previously?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't work without it. Honestly not sure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is always that chance that it had something to do with the gravitation and alignment of the planets... I'll try it later without it just to make sure.

:P

im.onload();
}, 0);
}
}
}

function addCacheString(url) {
return url + ((url.match(/\?/)) ? '&' : '?') + 'cache=' + (+new Date());
}

function getBase64(url, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var buffer = this.response,
binary = '',
bytes = new Uint8Array(buffer),
len = bytes.byteLength;

for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
callback(btoa(binary));
}
};
request.send();
}

function handleCanvasLayer(l, callback) {
l.redraw(function () {
var img = new Image();
img.src = l.canvas.toDataURL();
callback(null, {
img: img
});
})
}
};
89 changes: 76 additions & 13 deletions leaflet-image.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
(function(e){if("function"==typeof bootstrap)bootstrap("leafletimage",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeLeafletImage=e}else"undefined"!=typeof window?window.leafletImage=e():global.leafletImage=e()})(function(){var define,ses,bootstrap,module,exports;
return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.leafletImage = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var queue = require('./queue');

// leaflet-image
module.exports = function leafletImage(map, callback) {
module.exports = function leafletImage(map, callback, useAjax) {

var dimensions = map.getSize(),
layerQueue = new queue(1);
layerQueue = new queue(1),
imageCache = {};

var canvas = document.createElement('canvas');
canvas.width = dimensions.x;
Expand All @@ -30,17 +30,19 @@ module.exports = function leafletImage(map, callback) {
} else if (map._panes && map._panes.overlayPane.firstChild) {
layerQueue.defer(handlePathRoot, map._panes.overlayPane.firstChild);
}
map.eachLayer(drawMarkerLayer);
map.eachLayer(drawLayer);
layerQueue.awaitAll(layersDone);

function drawTileLayer(l) {
if (l instanceof L.TileLayer) layerQueue.defer(handleTileLayer, l);
else if (l._heat) layerQueue.defer(handlePathRoot, l._canvas);
}

function drawMarkerLayer(l) {
function drawLayer(l) {
if (l instanceof L.Marker && l.options.icon instanceof L.Icon) {
layerQueue.defer(handleMarkerLayer, l);
} else if (typeof l.redraw === 'function' && l.canvas) {
layerQueue.defer(handleCanvasLayer, l);
}
}

Expand All @@ -55,6 +57,11 @@ module.exports = function leafletImage(map, callback) {
ctx.drawImage(layer.canvas, 0, 0);
}
});
layers.forEach(function (layer) {
if (layer && layer.img && !layer.canvas) {
ctx.drawImage(layer.img, 0, 0);
}
});
done();
}

Expand Down Expand Up @@ -187,12 +194,14 @@ module.exports = function leafletImage(map, callback) {
minPoint = new L.Point(pixelBounds.min.x, pixelBounds.min.y),
pixelPoint = map.project(marker.getLatLng()),
isBase64 = /^data\:/.test(marker._icon.src),
cache = imageCache[marker._icon.src],
url = isBase64 ? marker._icon.src : addCacheString(marker._icon.src),
im = new Image(),
options = marker.options.icon.options,
size = options.iconSize,
pos = pixelPoint.subtract(minPoint),
anchor = L.point(options.iconAnchor || size && size.divideBy(2, true));
anchor = L.point(options.iconAnchor || size && size.divideBy(2, true)),
loaded = false;

if (size instanceof L.Point) size = [size.x, size.y];

Expand All @@ -204,20 +213,76 @@ module.exports = function leafletImage(map, callback) {
im.crossOrigin = '';

im.onload = function() {
if (loaded) return;
loaded = true;
ctx.drawImage(this, x, y, size[0], size[1]);
callback(null, {
canvas: canvas
});
};

im.src = url;
if (useAjax && !isBase64) {
if (cache === undefined) {
getBase64(url, function (data) {
im.src = imageCache[marker._icon.src] = 'data: image/png;base64, ' + data;
if (!loaded) {
setTimeout(function() {
im.onload();
},0);
}
});
} else {
im.src = cache;
if (!loaded) {
setTimeout(function() {
im.onload();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The image isn't yet added to the page, but is base64. setTimeout(fn, 0) ensures it is loaded when the next available context is, which (since we just set the src) is just after the src is rendered. Otherwise the image is not yet rendered, thus resulting in a blank image.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the tardy response.

},0);
}
}
} else {
im.src = url;

if (isBase64) im.onload();
if (isBase64 && !loaded) {
setTimeout(function () {
im.onload();
}, 0);
}
}
}

function addCacheString(url) {
return url + ((url.match(/\?/)) ? '&' : '?') + 'cache=' + (+new Date());
}

function getBase64(url, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var buffer = this.response,
binary = '',
bytes = new Uint8Array(buffer),
len = bytes.byteLength;

for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
callback(btoa(binary));
}
};
request.send();
}

function handleCanvasLayer(l, callback) {
l.redraw(function () {
var img = new Image();
img.src = l.canvas.toDataURL();
callback(null, {
img: img
});
})
}
};

},{"./queue":2}],2:[function(require,module,exports){
Expand Down Expand Up @@ -301,7 +366,5 @@ module.exports = function leafletImage(map, callback) {
function noop() {}
})();

},{}]},{},[1])
(1)
});
;
},{}]},{},[1])(1)
});