Wait to get canvas context until image is loaded, avoid some globals

This commit is contained in:
Bryan Housel
2018-06-22 11:41:29 -04:00
parent abbffd5e5b
commit d41cf5e6d8
2 changed files with 112 additions and 119 deletions
+110 -118
View File
@@ -29,15 +29,13 @@ var pannellumViewerCSS = 'pannellum-streetside/pannellum.css';
var pannellumViewerJS = 'pannellum-streetside/pannellum.js';
var maxResults = 2000;
var tileZoom = 16.5;
var numImgsPerFace = 16; // supported values are 4 or 16
var dispatch = d3_dispatch('loadedBubbles', 'viewerChanged');
var _currScene = 0;
var _ssCache;
var _pannellumViewer;
var _sceneOptions;
var _dataUrlArray = [];
var _faceImgInfoGroups = [];
// _numImgsPerFace: supported values are 4 or 16
var _numImgsPerFace = 16;
/**
* abortRequest().
@@ -308,11 +306,11 @@ function searchLimited(psize, limit, projection, rtree) {
*/
function getImage(imgInfo) {
var response = Q.defer();
var canvas = document.getElementById('canvas' + imgInfo.face);
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
var canvas = document.getElementById('canvas' + imgInfo.face);
var ctx = canvas.getContext('2d');
ctx.drawImage(img, imgInfo.dx, imgInfo.dy);
response.resolve({imgInfo:imgInfo, status: 'ok'});
};
@@ -331,10 +329,8 @@ function getImage(imgInfo) {
*/
function loadCanvas(imgInfoGroup) {
var response = Q.defer();
var getImagePromises = [];
imgInfoGroup.forEach(function(imgInfo){
getImagePromises.push(getImage(imgInfo));
var getImagePromises = imgInfoGroup.map(function(imgInfo) {
return getImage(imgInfo);
});
Q.all(getImagePromises).then(function(data) {
@@ -367,18 +363,16 @@ function loadCanvas(imgInfoGroup) {
/**
* processImages()
* processFaces()
*/
function processImages(imgFaceInfoGroups){
function processFaces(imgFaceInfoGroups) {
var response = Q.defer();
var loadCanvasPromises = [];
// call loadCanvas once with each group of infos....
imgFaceInfoGroups.forEach(function(faceImgGroup) {
loadCanvasPromises.push(loadCanvas(faceImgGroup));
var loadCanvasPromises = imgFaceInfoGroups.map(function(faceImgGroup) {
return loadCanvas(faceImgGroup);
});
Q.all(loadCanvasPromises).then(function() {
response.resolve({status: 'processImages done'});
response.resolve({status: 'processFaces done'});
});
return response.promise;
@@ -496,12 +490,7 @@ export default {
* loadViewer() create the streeside viewer.
*/
loadViewer: function (context) {
var whVal;
if (_numImgsPerFace === 4) {
whVal = '512';
} else if (_numImgsPerFace === 16) {
whVal = '1024';
}
var whVal = (numImgsPerFace === 16 ? '1024' : '512');
// create ms-wrapper, a photo wrapper class
var wrap = d3_select('#photoviewer').selectAll('.ms-wrapper')
@@ -579,7 +568,6 @@ export default {
_pannellumViewer
.removeScene(sceneID);
}
}
var wrap = d3_select('#photoviewer')
@@ -631,109 +619,113 @@ export default {
var wrap = d3_select('#photoviewer .ms-wrapper');
var attribution = wrap.selectAll('.photo-attribution').html('');
var year = (new Date()).getFullYear();
if (d) {
if (d.captured_by) {
attribution
.append('a')
.attr('class', 'captured_by')
.attr('target', '_blank')
.attr('href', 'https://www.microsoft.com/en-us/maps/streetside')
.text('©' + year + ' Microsoft');
wrap.selectAll('.pnlm-load-box') // display "loading.."
.style('display', 'block');
attribution
.append('span')
.text('|');
}
if (!d) {
response.resolve({status: 'ok'});
return response.promise;
}
if (d.captured_at) {
attribution
.append('span')
.attr('class', 'captured_at')
.text(localeTimestamp(d.captured_at));
}
if (d.captured_by) {
var yyyy = (new Date()).getFullYear();
attribution
.append('a')
.attr('class', 'image_link')
.attr('class', 'captured_by')
.attr('target', '_blank')
.attr('href', 'https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=' + encodeURIComponent(d.key) +
'&focus=photo&lat=' + d.loc[1] + '&lng=' + d.loc[0] + '&z=17')
.text(t('streetside.report'));
.attr('href', 'https://www.microsoft.com/en-us/maps/streetside')
.text('©' + yyyy + ' Microsoft');
var bubbleIdQuadKey = d.key.toString(4);
var paddingNeeded = 16 - bubbleIdQuadKey.length;
for (var i = 0; i < paddingNeeded; i++) {
bubbleIdQuadKey = '0' + bubbleIdQuadKey;
}
var imgUrlPrefix = streetsideImagesApi + 'hs' + bubbleIdQuadKey;
var imgUrlSuffix = '.jpg?g=6338&n=z';
// Cubemap face code order matters here: front=01, right=02, back=03, left=10, up=11, down=12
var imgFaceCodes = ['01','02','03','10','11','12'];
var faceLocCodes = null;
var faceLocPositions = null;
if (_numImgsPerFace === 4) {
faceLocCodes = [
'0','1','2','3'
];
faceLocPositions = [
{dx:0, dy:0}, {dx:256, dy:0}, {dx:0, dy:256}, {dx:256, dy:256}
];
} else if (_numImgsPerFace === 16) {
faceLocCodes = [
'00','01','02','03',
'10','11','12','13',
'20','21','22','23',
'30','31','32','33'
];
faceLocPositions = [
{dx:0, dy:0}, {dx:256, dy:0}, {dx:0, dy:256}, {dx:256, dy:256},
{dx:512, dy:0}, {dx:768, dy:0}, {dx:512, dy:256}, {dx:768, dy:256},
{dx:0, dy:512}, {dx:256, dy:512}, {dx:0, dy:768}, {dx:256, dy:768},
{dx:512, dy:512}, {dx:768, dy:512}, {dx:512, dy:768}, {dx:768, dy:768}
];
} else {
response.resolve({status:'error'});
}
// var fourImgPerFaceLocationCodes = ['0','1','2','3'];
// var fourImgPerFaceLocationPositions = [{dx:0,dy:0},{dx:256,dy:0},{dx:0,dy:256},{dx:256,dy:256}];
imgFaceCodes.forEach(function(faceCode) {
var faceImgInfoGroup = [];
faceLocCodes.forEach(function(loc,idx_l) {
var imgInfoObj = {};
imgInfoObj.face = faceCode;
imgInfoObj.url = imgUrlPrefix + faceCode + loc + imgUrlSuffix;
imgInfoObj.dx = faceLocPositions[idx_l].dx;
imgInfoObj.dy = faceLocPositions[idx_l].dy;
faceImgInfoGroup.push(imgInfoObj);
});
_faceImgInfoGroups.push(faceImgInfoGroup);
});
processImages(_faceImgInfoGroups).then(function() {
_sceneOptions = {
showFullscreenCtrl: false,
autoLoad: true,
compass: true,
northOffset: d.ca,
yaw: 0,
type: 'cubemap',
cubeMap: [
_dataUrlArray[0],
_dataUrlArray[1],
_dataUrlArray[2],
_dataUrlArray[3],
_dataUrlArray[4],
_dataUrlArray[5]
]
};
response.resolve({status: 'ok'});
});
attribution
.append('span')
.text('|');
}
if (d.captured_at) {
attribution
.append('span')
.attr('class', 'captured_at')
.text(localeTimestamp(d.captured_at));
}
attribution
.append('a')
.attr('class', 'image_link')
.attr('target', '_blank')
.attr('href', 'https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=' + encodeURIComponent(d.key) +
'&focus=photo&lat=' + d.loc[1] + '&lng=' + d.loc[0] + '&z=17')
.text(t('streetside.report'));
var bubbleIdQuadKey = d.key.toString(4);
var paddingNeeded = 16 - bubbleIdQuadKey.length;
for (var i = 0; i < paddingNeeded; i++) {
bubbleIdQuadKey = '0' + bubbleIdQuadKey;
}
var imgUrlPrefix = streetsideImagesApi + 'hs' + bubbleIdQuadKey;
var imgUrlSuffix = '.jpg?g=6338&n=z';
// Map images to cube faces
var faceLocCodes = null;
var faceLocPositions = null;
if (numImgsPerFace === 16) {
faceLocCodes = [
'00','01','02','03',
'10','11','12','13',
'20','21','22','23',
'30','31','32','33'
];
faceLocPositions = [
{dx:0, dy:0}, {dx:256, dy:0}, {dx:0, dy:256}, {dx:256, dy:256},
{dx:512, dy:0}, {dx:768, dy:0}, {dx:512, dy:256}, {dx:768, dy:256},
{dx:0, dy:512}, {dx:256, dy:512}, {dx:0, dy:768}, {dx:256, dy:768},
{dx:512, dy:512}, {dx:768, dy:512}, {dx:512, dy:768}, {dx:768, dy:768}
];
} else { // numImgsPerFace === 4
faceLocCodes = [
'0','1','2','3'
];
faceLocPositions = [
{dx:0, dy:0}, {dx:256, dy:0}, {dx:0, dy:256}, {dx:256, dy:256}
];
}
// Cubemap face code order matters here: front=01, right=02, back=03, left=10, up=11, down=12
var faceCodes = ['01','02','03','10','11','12'];
var faces = faceCodes.map(function(faceCode) {
return faceLocCodes.map(function(loc, i) {
return {
face: faceCode,
url: imgUrlPrefix + faceCode + loc + imgUrlSuffix,
dx: faceLocPositions[i].dx,
dy: faceLocPositions[i].dy
};
});
});
processFaces(faces).then(function() {
_sceneOptions = {
showFullscreenCtrl: false,
autoLoad: true,
compass: true,
northOffset: d.ca,
yaw: 0,
type: 'cubemap',
cubeMap: [
_dataUrlArray[0],
_dataUrlArray[1],
_dataUrlArray[2],
_dataUrlArray[3],
_dataUrlArray[4],
_dataUrlArray[5]
]
};
response.resolve({status: 'ok'});
});
return response.promise;
},
+2 -1
View File
@@ -104,7 +104,8 @@ export function svgStreetside(projection, context, dispatch) {
_selectedSequence = d.sequenceKey;
service
.selectImage(d).then(function(r){
.selectImage(d)
.then(function(r) {
if (r.status === 'ok'){
service.showViewer(_viewerYaw);
}