Skip to content

Commit

Permalink
Merge pull request #40 from zilliztech/separate_layout_and_render
Browse files Browse the repository at this point in the history
Separate layout and render
  • Loading branch information
shanghaikid committed Jun 16, 2022
2 parents eeb3224 + 0eb8e0b commit 83dbbfe
Show file tree
Hide file tree
Showing 56 changed files with 7,461 additions and 1,859 deletions.
82 changes: 46 additions & 36 deletions federjs/Feder.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class Feder {
this.federView = new FederView({ domSelector, viewParams });
this.viewParams = viewParams;
if (!core) {
this.initCorePromise = fetch(filePath)
this.initCoreAndViewPromise = fetch(filePath)
.then((res) => res.arrayBuffer())
.then((data) => {
core = new FederCore({ data, source, viewParams });
Expand All @@ -31,59 +31,69 @@ export default class Feder {
}
}

get node() {
return this.federView.dom;
overview() {
return this.federView.overview(this.initCoreAndViewPromise);
}
async overview() {
this.initCorePromise && (await this.initCorePromise);
this.federView.overview();
}
async search(target = null, targetMediaUrl = null) {
this.initCorePromise && (await this.initCorePromise);
search(target = null, targetMediaUrl = null) {
if (target) {
const searchRes = this.core.search(target);
console.log(searchRes);
this.searchRes = searchRes;
this.federView.search({ searchRes, targetMediaUrl });
const searchResPromise = this.initCoreAndViewPromise.then(() => {
const searchRes = this.core.search(target);
console.log(searchRes);
this.searchRes = searchRes;
this.targetMediaUrl = targetMediaUrl;
return { searchRes, targetMediaUrl };
});
return this.federView.search({ searchResPromise });
} else {
if (!this.searchRes) {
console.error('No target');
return;
}
const searchRes = this.searchRes;
const targetMediaUrl = this.targetMediaUrl;
this.federView.search({ searchRes, targetMediaUrl });
return this.federView.search({ searchRes, targetMediaUrl });
}
}
async searchById(testId = null) {
this.initCorePromise && (await this.initCorePromise);
if (!(testId in this.core.id2vector)) {
console.log('Invalid Id');
} else {
const testVec = this.core.id2vector[testId];
searchById(testId) {
const searchResPromise = this.initCoreAndViewPromise.then(() => {
if (!(testId in this.core.id2vector)) {
console.error('Invalid Id');
} else {
const testVec = this.core.id2vector[testId];
const targetMediaUrl =
this.viewParams && this.viewParams.mediaCallback
? this.viewParams.mediaCallback(testId)
: null;
const searchRes = this.core.search(testVec);
console.log(searchRes);
this.searchRes = searchRes;
return { searchRes, targetMediaUrl };
}
});
return this.federView.search({ searchResPromise });
}
searchRandTestVec() {
const searchResPromise = this.initCoreAndViewPromise.then(() => {
let [testId, testVec] = this.core.getTestIdAndVec();
while (isNaN(testId)) {
[testId, testVec] = this.core.getTestIdAndVec();
}
console.log('random test vector:', testId, testVec);
const targetMediaUrl =
this.viewParams && this.viewParams.mediaCallback
? this.viewParams.mediaCallback(testId)
: null;
this.search(testVec, targetMediaUrl);
}
}
async searchRandTestVec() {
this.initCorePromise && (await this.initCorePromise);
let [testId, testVec] = await this.core.getTestIdAndVec();
while (isNaN(testId)) {
[testId, testVec] = await this.core.getTestIdAndVec();
}
console.log('random test vector:', testId, testVec);
const targetMediaUrl =
this.viewParams && this.viewParams.mediaCallback
? this.viewParams.mediaCallback(testId)
: null;
this.search(testVec, targetMediaUrl);
const searchRes = this.core.search(testVec);
console.log(searchRes);
this.searchRes = searchRes;
return { searchRes, targetMediaUrl };
});

return this.federView.search({ searchResPromise });
}

async setSearchParams(params) {
this.initCorePromise && (await this.initCorePromise);
this.initCoreAndViewPromise && (await this.initCoreAndViewPromise);
if (!this.core) {
console.error('No feder-core');
} else {
Expand Down
145 changes: 85 additions & 60 deletions federjs/FederView/BaseView.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as d3 from 'd3';
import { renderLoading, finishLoading } from './loading';
import { VIEW_TYPE } from 'Types';
// import { VIEW_TYPE } from 'Types';

export default class BaseView {
constructor({ dom, viewParams, getVectorById }) {
this.dom = dom;
constructor({ viewParams, getVectorById }) {
this.viewParams = viewParams;

const { width, height, canvasScale, mediaType, mediaCallback } = viewParams;
Expand All @@ -17,68 +16,94 @@ export default class BaseView {
this.mediaType = mediaType;
this.mediaCallback = mediaCallback;
}
initCanvas() {
renderLoading(this.dom, this.viewParams.width, this.viewParams.height);
const dom = d3.select(this.dom);
dom.selectAll('canvas').remove();
const canvas = dom
.append('canvas')
.attr('width', this.clientWidth)
.attr('height', this.clientHeight);
const ctx = canvas.node().getContext('2d');
ctx.scale(1 / this.canvasScale, 1 / this.canvasScale);
this.ctx = ctx;
this.canvas = canvas.node();
}

// override
overviewHandler() {}
initInfoPanel() {}
renderOverview() {}
renderSearchView() {}
setOverviewListenerHandlers() {}
setSearchViewListenerHandlers() {}
searchViewHandler() {}
getOverviewEventHandler() {}
getSearchViewEventHandler() {}

async overview() {
this.viewType = VIEW_TYPE.overview;
this.initCanvas();
this.clickedNode = null;
this.hoveredNode = null;
this.overviewInitPromise && (await this.overviewInitPromise);
finishLoading(this.dom);
this.renderOverview();
this.addMouseListener();
this.setOverviewListenerHandlers();
}
async search({ searchRes, targetMediaUrl }) {
this.viewType = VIEW_TYPE.search;
this.targetMediaUrl = targetMediaUrl;
this.initCanvas();
this.clickedNode = null;
this.hoveredNode = null;
await this.searchViewHandler({ searchRes });
finishLoading(this.dom);
this.renderSearchView();
this.addMouseListener();
this.setSearchViewListenerHandlers();
async overview(dom) {
const canvas = initCanvas(
dom,
this.clientWidth,
this.clientHeight,
this.canvasScale
);
const ctx = canvas.getContext('2d');
const infoPanel = this.initInfoPanel(dom);

this.overviewLayoutPromise && (await this.overviewLayoutPromise);
finishLoading(dom);
this.renderOverview(ctx, infoPanel);
const eventHandlers = this.getOverviewEventHandler(ctx, infoPanel);
addMouseListener(canvas, this.canvasScale, eventHandlers);
}

addMouseListener() {
const canvas = this.canvas;
const canvasScale = this.canvasScale;
canvas.addEventListener('mousemove', (e) => {
const { offsetX, offsetY } = e;
const x = offsetX * canvasScale;
const y = offsetY * canvasScale;
this.mouseMoveHandler && this.mouseMoveHandler({ x, y });
});
canvas.addEventListener('click', (e) => {
const { offsetX, offsetY } = e;
const x = offsetX * canvasScale;
const y = offsetY * canvasScale;
this.mouseClickHandler && this.mouseClickHandler({ x, y });
});
canvas.addEventListener('mouseleave', () => {
this.mouse = null;
this.mouseLeaveHandler && this.mouseLeaveHandler();
});
async search(dom, { searchRes, targetMediaUrl }) {
const canvas = initCanvas(
dom,
this.clientWidth,
this.clientHeight,
this.canvasScale
);
const ctx = canvas.getContext('2d');
const infoPanel = this.initInfoPanel(dom);

const searchViewLayoutData = await this.searchViewHandler(searchRes);
finishLoading(dom);
this.renderSearchView(
ctx,
infoPanel,
searchViewLayoutData,
targetMediaUrl,
dom
);
const eventHandlers = this.getSearchViewEventHandler(
ctx,
searchViewLayoutData,
infoPanel
);
addMouseListener(canvas, this.canvasScale, eventHandlers);
}
}

const addMouseListener = (
element,
canvasScale,
{ mouseMoveHandler, mouseClickHandler, mouseLeaveHandler } = {}
) => {
element.addEventListener('mousemove', (e) => {
const { offsetX, offsetY } = e;
const x = offsetX * canvasScale;
const y = offsetY * canvasScale;
mouseMoveHandler && mouseMoveHandler({ x, y });
});
element.addEventListener('click', (e) => {
const { offsetX, offsetY } = e;
const x = offsetX * canvasScale;
const y = offsetY * canvasScale;
mouseClickHandler && mouseClickHandler({ x, y });
});
element.addEventListener('mouseleave', () => {
mouseLeaveHandler && mouseLeaveHandler();
});
};

const initCanvas = (dom, clientWidth, clientHeight, canvasScale) => {
renderLoading(dom, clientWidth, clientHeight);

const domD3 = d3.select(dom);
domD3.selectAll('canvas').remove();

const canvas = domD3
.append('canvas')
.attr('width', clientWidth)
.attr('height', clientHeight);
const ctx = canvas.node().getContext('2d');
ctx.scale(1 / canvasScale, 1 / canvasScale);

return canvas.node();
};
Loading

0 comments on commit 83dbbfe

Please sign in to comment.