Skip to content

Commit

Permalink
splitting big canvas into chunks and minor fixes, for Caleydo/lineup_…
Browse files Browse the repository at this point in the history
  • Loading branch information
domdir committed Sep 7, 2018
1 parent 391fd54 commit 80fc751
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/model/OverviewDetailColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface IDetailColumnDesc extends IValueColumnDesc<boolean> {
* a checkbox column for selections
*/
@SupportType()
@toolbar('sort', 'stratify', 'selectionToOverviewDetail', 'overviewDetailToSelection')
@toolbar('sort', 'sortBy', 'group', 'groupBy', 'selectionToOverviewDetail', 'overviewDetailToSelection')
@Category('support')
export default class OverviewDetailColumn extends ValueColumn<boolean> {
private static DETAILED_GROUP: IGroup = {
Expand Down
3 changes: 3 additions & 0 deletions src/styles/engine/_texture_renderer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
.columnContainer {
flex: 0 0 auto;
margin-right: 5px;
display: flex;
flex-direction: column;
justify-content: space-between;

&.partOfComposite {
margin-right: 6px;
Expand Down
100 changes: 54 additions & 46 deletions src/ui/CanvasTextureRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface ITextureRenderer {
}

export default class CanvasTextureRenderer implements ITextureRenderer {
static readonly MAX_CANVAS_SIZE = 32767;

readonly node: HTMLElement;
readonly canvas: any;
Expand Down Expand Up @@ -134,26 +135,23 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
this.detailParts.splice(j, 0, g);
aggregateIndices.push(j);
return;
} else {
if (g[1] < this.detailParts[j][1]) {
this.detailParts.splice(j, 1, g, [g[1] + 1, this.detailParts[j][1]]);
aggregateIndices.push(j);
return;
} else {
this.detailParts.splice(j, 1);
}
}
} else {
if (g[0] <= this.detailParts[j][1]) {
if (g[1] < this.detailParts[j][1]) {
this.detailParts.splice(j, 1, [this.detailParts[j][0], g[0] - 1], g, [g[1] + 1, this.detailParts[j][1]]);
aggregateIndices.push(j + 1);
return;
} else {
this.detailParts.splice(j, 1, [this.detailParts[j][0], g[0] - 1]);
}
if (g[1] < this.detailParts[j][1]) {
this.detailParts.splice(j, 1, g, [g[1] + 1, this.detailParts[j][1]]);
aggregateIndices.push(j);
return;
}
this.detailParts.splice(j, 1);
}
if (g[0] > this.detailParts[j][1]) {
return;
}
if (g[1] < this.detailParts[j][1]) {
this.detailParts.splice(j, 1, [this.detailParts[j][0], g[0] - 1], g, [g[1] + 1, this.detailParts[j][1]]);
aggregateIndices.push(j + 1);
return;
}
this.detailParts.splice(j, 1, [this.detailParts[j][0], g[0] - 1]);
}
this.detailParts.push(g);
aggregateIndices.push(this.detailParts.length - 1);
Expand Down Expand Up @@ -183,7 +181,6 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
dataParts.push(localData[i].length);
}
}
//
let curIndex = 0;
const rankingDiv = <any>d3.select(this.node).select(`[data-ranking="${rankingIndex}"]`)!.node();
if (!rankingDiv) {
Expand Down Expand Up @@ -211,15 +208,18 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
aggregateOffset += newOffset;

if (!aggregated) {
const textureDiv = this.node.ownerDocument.createElement('div');
textureDiv.style.height = `${data.length / localData[i].length * this.currentNodeHeight}px`;
textureDiv.classList.add('textureContainer');
if (!expandable) {
textureDiv.classList.add('always');
const height = data.length / localData[i].length * this.currentNodeHeight;
if (height >= 1) { //only render parts larger than 1px
const textureDiv = this.node.ownerDocument.createElement('div');
textureDiv.style.height = `${height}px`;
textureDiv.classList.add('textureContainer');
if (!expandable) {
textureDiv.classList.add('always');
}
this.renderedColumns = [];
r.ranking.flatColumns.forEach((column) => this.createColumn(column, data, textureDiv, false, expandable));
rowDiv.appendChild(textureDiv);
}
this.renderedColumns = [];
r.ranking.flatColumns.forEach((column) => this.createColumn(column, data, textureDiv, false, expandable));
rowDiv.appendChild(textureDiv);
}
if (expandable) {
const expandLater = () => {
Expand Down Expand Up @@ -294,46 +294,46 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
columnContainer.classList.add('partOfComposite');
}

let newElement = <any>null;
let newElements = <any>[];
if (column instanceof NumbersColumn) {
const col = <NumbersColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return (<any>value).v[(<any>col.desc).column];
}), CanvasTextureRenderer.getColorScale(col));
} else if (column instanceof NumberColumn) {
const col = <NumberColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return [(<any>value).v[(<any>col.desc).column]];
}), CanvasTextureRenderer.getColorScale(col));
} else if (column instanceof CategoricalsColumn) {
const col = <CategoricalsColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return (<any>value).v[(<any>col.desc).column];
}), CanvasTextureRenderer.getColorScale(col));
} else if (column instanceof CategoricalColumn) {
const col = <CategoricalColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return [(<any>value).v[(<any>col.desc).column]];
}), CanvasTextureRenderer.getColorScale(col));
} else if (column instanceof SelectionColumn) {
const col = <SelectionColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return [this.engineRenderer.ctx.provider.isSelected((<any>value).i)];
}), CanvasTextureRenderer.getColorScale(col));
} else if (column instanceof OverviewDetailColumn) {
const col = <OverviewDetailColumn>column;
newElement = this.generateImage(grouped.map((value) => {
newElements = this.generateImage(grouped.map((value) => {
return [this.engineRenderer.ctx.provider.isDetail((<any>value).i)];
}), CanvasTextureRenderer.getColorScale(col));
} else if ('children' in column) {
//handle composite columns
(<CompositeColumn>column).children.forEach((c) => this.createColumn(c, grouped, container, true, expandable));
return;
} else {
newElement = this.node.ownerDocument.createElement('canvas');
newElements.push(this.node.ownerDocument.createElement('canvas'));
}

columnContainer.appendChild(newElement);
newElements.forEach((newElement: any) => columnContainer.appendChild(newElement));

container.appendChild(columnContainer);
this.renderedColumns.push(column.id);
Expand All @@ -356,10 +356,10 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
return colorScale;
}
if (column instanceof CategoricalColumn) {
const colorScale = scaleOrdinal<number, string>();
const colorScale = scaleOrdinal<string, string>();
const categories = column.categories;
colorScale
.domain(categories.map((v) => v.value))
.domain(categories.map((v) => v.name))
.range(categories.map((v) => v.color));
return colorScale;
}
Expand All @@ -383,16 +383,24 @@ export default class CanvasTextureRenderer implements ITextureRenderer {
}

private generateImage(data: any[][], colorScale: any) {
const height = data.length;
let width = 0;
if(height > 0) {
width = data[0].length;
const totalLength = data.length;
const newElements = <any>[];
while (data.length > 0) {
const chunk = data.splice(0, CanvasTextureRenderer.MAX_CANVAS_SIZE);
const height = chunk.length;
let width = 0;
if(height > 0) {
width = chunk[0].length;
}
const canvas = this.node.ownerDocument.createElement('canvas');
canvas.setAttribute('height', `${height}`);
canvas.setAttribute('width', `${width}`);
canvas.style.flexGrow = `${height}`;
canvas.style.height = `${chunk.length / totalLength * 100}%`;
this.drawOntoCanvas(chunk, colorScale, canvas);
newElements.push(canvas);
}
const canvas = this.node.ownerDocument.createElement('canvas');
canvas.setAttribute('height', `${height}`);
canvas.setAttribute('width', `${width}`);
this.drawOntoCanvas(data, colorScale, canvas);
return canvas;
return newElements;
}

private drawOntoCanvas(data: any[][], colorScale: any, canvas: any) {
Expand Down
28 changes: 20 additions & 8 deletions src/ui/taggle/Taggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,22 @@ export default class Taggle extends ALineUp {
this.renderer.pushUpdateAble((ctx) => this.panel!.update(ctx));
this.node.insertBefore(this.panel.node, this.node.firstChild);
{
this.panel.node.insertAdjacentHTML('afterbegin', `<div class="lu-expand-button-chooser"><label>
<input class="expand" type="checkbox">
<span>Expand</span>
</label></div>`);
const expandButton = <HTMLElement>this.node.querySelector('.lu-expand-button-chooser')!;
const expandInput = <HTMLInputElement>expandButton.querySelector('input.expand');
expandInput.onchange = () => {
const selected = expandInput.checked;
this.renderer!.expandTextureRenderer(selected);
};
expandButton.onclick = () => {
expandInput.checked = !expandInput.checked;
};
this.panel.node.insertAdjacentHTML('afterbegin', `<div class="lu-rule-button-chooser"><label>
<input class="spaceFilling" type="checkbox">
<span>Overview</span>
<input id="lu-toggle-expand" class="expand" type="checkbox">
<span for="lu-toggle-expand">Expand</span>
<div></div>
</label></div>`);
const spaceFilling = spaceFillingRule(this.options);
this.spaceFilling = <HTMLElement>this.node.querySelector('.lu-rule-button-chooser')!;
Expand All @@ -54,17 +64,19 @@ export default class Taggle extends ALineUp {
const selected = this.spaceFilling!.classList.toggle('chosen');
//self.setTimeout(() => this.renderer.switchRule(selected ? spaceFilling : null));
this.renderer!.useTextureRenderer(selected);
if (selected) {
expandButton.style.display = '';
} else {
expandButton.style.display = 'none';
}
};
if (this.options.overviewMode) {
ruleInput.checked = true;
this.spaceFilling.classList.toggle('chosen');
this.renderer.switchRule(spaceFilling);
} else {
expandButton.style.display = 'none';
}
const expandInput = <HTMLInputElement>this.spaceFilling.querySelector('input.expand');
expandInput.onchange = () => {
const selected = expandInput.checked;
this.renderer!.expandTextureRenderer(selected);
};
}
this.forward(this.renderer, `${ALineUp.EVENT_HIGHLIGHT_CHANGED}.main`);
}
Expand Down

0 comments on commit 80fc751

Please sign in to comment.