class ImageFetcher {
constructor() {
this.imagesIdByUrl = {};
this.imagesById = {};
this.dispatcher = d3.dispatch('image');
this.errors = {};
this.dispatcher.on('image', ({ imageId, url, data, error }) => {
console.log('event received:', {
url,
data,
imageId,
error,
imagesIdByUrl: this.imagesIdByUrl,
imagesById: this.imagesById
});
if (error) {
console.error('file reading error', { url, data, imageId, error });
return null;
}
d3.selectAll(`image[data-image-id="${imageId}"]`).attr('href', data);
});
}
makeId() {
return `img-${getRandomId()}`;
}
addImage({ url, x = 0, y = 0, width, height, className }) {
const _url = encodeURI(url);
let imageId = this.makeId();
console.log('addImage() registering image', {
url,
x,
y,
width,
height,
imageId,
url
});
if (!this.imagesIdByUrl[_url]) {
this.imagesIdByUrl[_url] = imageId;
axios
.get(_url, { responseType: 'blob' })
.then(this.onFetch({ imageId, url: _url, width, height }))
.catch(this.onError({ imageId, url: _url }));
} else {
imageId = this.imagesIdByUrl[_url];
}
return node =>
node
.append('image')
.attr('class', className)
.attr('data-image-id', imageId)
.attr(...ttrans(x, y))
.attr('width', width)
.attr('height', height);
}
addImageByDataKey({ dataKey, x = 0, y = 0, width, height, className }) {
return node =>
node.each((d, i, a) => {
let imageId = this.makeId();
const _url = _.get(d.data, dataKey);
if (!_url || _url === '') {
return null;
}
const url = encodeURI(_url);
const isDupe = this.imagesIdByUrl[url];
if (isDupe) imageId = this.imagesIdByUrl[url];
else this.imagesIdByUrl[url] = imageId;
console.log('addImageByDataKey() registering image', {
dataKey,
x,
y,
width,
height,
imageId,
url
});
d3.select(a[i])
.append('image')
.attr('class', className)
.attr('data-image-id', imageId)
.attr(...ttrans(x, y))
.attr('width', width)
.attr('height', height);
if (!isDupe) {
axios
.get(url, { responseType: 'blob' })
.then(this.onFetch({ imageId, url, width, height }))
.catch(this.onError({ imageId, url }));
}
});
}
onError({ imageId, url }) {
return err =>
this.dispatcher.call('image', null, {
imageId,
url,
data: null,
error: err
});
}
onFetch({ imageId, url }) {
return response => {
const reader = new FileReader();
reader.onloadend = () =>
this.onFileReady({ data: reader.result, imageId, url });
reader.readAsDataURL(response.data);
};
}
onFileReady({ data, imageId, url }) {
this.imagesById[imageId] = data;
this.dispatcher.call('image', null, { imageId, url, data, error: null });
}
}