Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions src/marks/raster.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {blurImage, Delaunay, randomLcg, rgb} from "d3";
import {blurImage, Delaunay, randomLcg} from "d3";
import {valueObject} from "../channel.js";
import {create} from "../context.js";
import {map, first, second, third, isTuples, isNumeric, isTemporal, identity} from "../options.js";
Expand Down Expand Up @@ -105,7 +105,6 @@ export class Raster extends AbstractRaster {
const dx = x2 - x1;
const dy = y2 - y1;
const {pixelSize: k, width: w = Math.round(Math.abs(dx) / k), height: h = Math.round(Math.abs(dy) / k)} = this;
const n = w * h;

// Interpolate the samples to fill the raster grid. If interpolate is null,
// then a continuous function is being sampled, and the raster grid is
Expand All @@ -123,35 +122,37 @@ export class Raster extends AbstractRaster {

// When faceting without interpolation, as when sampling a continuous
// function, offset into the dense grid based on the current facet index.
else if (this.data == null && index) offset = index.fi * n;
else if (this.data == null && index) offset = index.fi * w * h;

// Render the raster grid to the canvas, blurring if needed.
// Render the raster grid to the canvas.
const canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
const context2d = canvas.getContext("2d");
const image = context2d.createImageData(w, h);
const imageData = image.data;
let {r, g, b} = rgb(this.fill) ?? {r: 0, g: 0, b: 0};
let a = (this.fillOpacity ?? 1) * 255;
for (let i = 0; i < n; ++i) {
const j = i << 2;
if (F) {
const fi = color(F[i + offset]);
if (fi == null) {
imageData[j + 3] = 0;
continue;
if (!F) context2d.fillStyle = this.fill ?? "black";
if (!FO) context2d.globalAlpha = this.fillOpacity ?? 1;
for (let i = offset, y = 0; y < h; ++y) {
for (let x = 0; x < w; ++x, ++i) {
if (F) {
const f = color(F[i]);
if (f == null) continue;
context2d.fillStyle = f;
}
({r, g, b} = rgb(fi));
if (FO) {
const o = FO[i];
if (o == null) continue;
context2d.globalAlpha = o;
}
context2d.fillRect(x, y, 1, 1);
}
if (FO) a = FO[i + offset] * 255;
imageData[j + 0] = r;
imageData[j + 1] = g;
imageData[j + 2] = b;
imageData[j + 3] = a;
}
if (this.blur > 0) blurImage(image, this.blur);
context2d.putImageData(image, 0, 0);

// Blur if needed.
if (this.blur > 0) {
const image = context2d.getImageData(0, 0, w, h);
blurImage(image, this.blur);
context2d.putImageData(image, 0, 0);
}

return create("svg:g", context)
.call(applyIndirectStyles, this, dimensions, context)
Expand Down
2 changes: 1 addition & 1 deletion test/output/heatmapFillOpacity.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/output/heatmapOpacity.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/output/rasterWalmartBarycentricOpacity.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/output/rasterWalmartWalkOpacity.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.