diff --git a/README.md b/README.md index ee4daf12..7f93ea16 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@

-# Falcon: Interactive Visual Analysis for Big Data +### Shapelets falcon fork -[![npm version](https://img.shields.io/npm/v/falcon-vis.svg)](https://www.npmjs.com/package/falcon-vis) [![Build Status](https://travis-ci.com/uwdata/falcon.svg?branch=master)](https://travis-ci.com/uwdata/falcon) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=rounded)](https://github.com/prettier/prettier) [![Greenkeeper badge](https://badges.greenkeeper.io/uwdata/falcon.svg)](https://greenkeeper.io/) +This fork allows you to use falcon responsive and change fill color of the bar. Thanks to Dominik Moritz for his support from the original falcon repository. + +[![npm version](https://img.shields.io/npm/v/shapelets-falcon.svg)](https://www.npmjs.com/package/shapelets-falcon) Crossfilter millions of records without latencies. This project is work in progress and not documented yet. Please get in touch if you have questions. diff --git a/flights-responsive/app.scss b/flights-responsive/app.scss new file mode 100644 index 00000000..51ba1417 --- /dev/null +++ b/flights-responsive/app.scss @@ -0,0 +1,3 @@ +#app { + height: 100vh; +} diff --git a/flights-responsive/index.html b/flights-responsive/index.html new file mode 100644 index 00000000..2b057e7d --- /dev/null +++ b/flights-responsive/index.html @@ -0,0 +1,21 @@ + + + + + + + + + Explore Flights in Falcon + + + + + +
Loading data. Please wait...
+
+
+ + + + diff --git a/flights-responsive/index.ts b/flights-responsive/index.ts new file mode 100644 index 00000000..ec90f70d --- /dev/null +++ b/flights-responsive/index.ts @@ -0,0 +1,104 @@ +import { App, ArrowDB, Logger, Views } from "../src"; +import { createElement } from "./utils"; + +document.getElementById("app")!.innerText = ""; + +type ViewName = + | "DEP_TIME" + | "ARR_TIME"; + +type DimensionName = + | "ARR_TIME" + | "DEP_TIME"; + +const views: Views = new Map(); + +views.set("ARR_TIME", { + title: "Arrival Time", + type: "1D", + el: createElement("arrival", 2), + dimension: { + name: "ARR_TIME", + bins: 24, + extent: [0, 24], + format: ".1f" + } +}); +views.set("DEP_TIME", { + title: "Departure Time", + type: "1D", + el: createElement("departure", 2), + dimension: { + name: "DEP_TIME", + bins: 24, + extent: [0, 24], + format: ".1f" + } +}); + +const url = require("../data/flights-10k.arrow"); +// const url = +// "https://media.githubusercontent.com/media/uwdata/flights-arrow/master/flights-10m.arrow"; +const db = new ArrowDB(url); + +let logger: Logger | undefined; + +//============= +// timeline vis logger + +// logger = new TimelineLogger(createElement("logs"), views); + +//============= +// simple logger as demo + +// logger = new SimpleLogger(); + +const iPad = !!navigator.userAgent.match(/iPad/i); + +new App(views, db, { + config: { + barWidth: 600, + fillColor: '#00f0ff', + responsive: true, + ...(iPad + ? { + barWidth: 450, + histogramWidth: 450, + histogramHeight: 120, + heatmapWidth: 300, + prefetchOn: "mousedown" + } + : {}) + }, + logger: logger, + cb: _app => { + document.getElementById("loading")!.style.display = "none"; + + //============= + // benchmark + + // function animationframe() { + // return new Promise(resolve => requestAnimationFrame(resolve)); + // } + + // async function benchmark() { + // _app.prefetchView("AIR_TIME", false); + + // console.time("Brushes"); + // const step = 25; + // for (let start = 0; start < 500; start += step) { + // for (let end = start + step; end < 500 + step; end += step) { + // _app + // .getVegaView("AIR_TIME") + // .signal("brush", [start, end]) + // .run(); + + // await animationframe(); + // } + // } + // console.timeEnd("Brushes"); + // } + + // window.setTimeout(benchmark, 1000); + } +}); diff --git a/flights-responsive/utils.ts b/flights-responsive/utils.ts new file mode 100644 index 00000000..dad1438a --- /dev/null +++ b/flights-responsive/utils.ts @@ -0,0 +1,14 @@ +import { version } from "../src"; + +document.getElementById( + "version" +)!.innerHTML = `Powered by Falcon ${version}`; + +export function createElement(id: string, numOfElements: number) { + const el = document.createElement("div"); + el.setAttribute("id", id); + el.style.height = `calc(100% / ${numOfElements})`; + el.style.width = '100%'; + document.getElementById("app")!.appendChild(el); + return el; +} diff --git a/package.json b/package.json index bcfe7f0e..c66a34e6 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,20 @@ { - "name": "falcon-vis", - "version": "0.14.3", - "description": "Big data crossfilter", + "name": "shapelets-falcon", + "version": "0.14.5", + "description": "Big data crossfilter fork from falcon", "main": "build/falcon.js", "module": "build/src/index", "types": "build/src/index.d.ts", "scripts": { + "start:flights-responsive": "parcel flights-responsive/index.html", "start:flights": "parcel flights/index.html", "start:flights-mapd": "parcel flights-mapd/index.html", "start:weather": "parcel weather/index.html", "start:gaia-mapd": "parcel gaia-mapd/index.html", "start": "yarn start:flights", "clean": "rm -rf dist && rm -rf .cache && rm -rf build", - "build": "tsc && rollup -c", - "build:demos": "parcel build --public-url '/falcon/' flights/index.html flights-mapd/index.html weather/index.html --detailed-report", + "build": "tsc --declaration && rollup -c", + "build:demos": "parcel build --public-url '/falcon/' flights/index.html flights-responsive/index.html flights-mapd/index.html weather/index.html --detailed-report", "deploy:demos": "yarn clean && yarn build:demos && gh-pages -d dist", "test": "jest", "prettierbase": "prettier '{src,test}/**/*.{ts,html,scss}'", @@ -23,14 +24,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/uwdata/falcon.git" + "url": "git+https://github.com/shapelets/falcon" }, - "author": "Dominik Moritz", + "author": "José Sánchez Aranda", "license": "BSD-3-Clause", "bugs": { - "url": "https://github.com/uwdata/falcon/issues" + "url": "https://github.com/shapelets/falcon/issues" }, - "homepage": "https://github.com/uwdata/falcon#readme", + "homepage": "https://github.com/shapelets/falcon#readme", "dependencies": { "@apache-arrow/es2015-esm": "^0.14.1", "@mapd/connector": "^4.7.2", @@ -42,6 +43,7 @@ "ndarray-linear-interpolate": "^1.0.0", "ndarray-ops": "^1.2.2", "ndarray-prefix-sum": "^1.0.0", + "resize-detector": "^0.2.0", "vega": "^5.4.0" }, "devDependencies": { diff --git a/src/app.ts b/src/app.ts index 7c22e0b9..ef228bf8 100644 --- a/src/app.ts +++ b/src/app.ts @@ -29,6 +29,7 @@ import { createVerticalBarView } from "./views"; // import imshow from "ndarray-imshow"; +import * as resizeDetector from "resize-detector"; const interp2d = interpolate.d2; @@ -271,6 +272,14 @@ export class App { const el = view.el!; let vegaView: VgView; + if (this.config.responsive) { + resizeDetector.addListener(el, () => { + vegaView.width(el.offsetWidth - 10); + vegaView.height(el.offsetHeight - 20); + vegaView.runAsync(); + }); + } + if (view.type === "0D") { vegaView = (this.config.zeroD === "text" ? createTextView @@ -278,6 +287,8 @@ export class App { ? createHorizontalBarView : createVerticalBarView)(el, view, this.config); + vegaView.width(el.offsetWidth - 10); + vegaView.height(el.offsetHeight - 20); await vegaView.runAsync(); this.vegaViews.set(name, vegaView); @@ -293,6 +304,8 @@ export class App { vegaView = createHistogramView(el, view, this.config, !!this.logger); + vegaView.width(el.offsetWidth - 10); + vegaView.height(el.offsetHeight - 20); await vegaView.runAsync(); this.vegaViews.set(name, vegaView); @@ -343,6 +356,8 @@ export class App { vegaView = createHeatmapView(el, view, this.config); + vegaView.width(el.offsetWidth - 10); + vegaView.height(el.offsetHeight - 20); await vegaView.runAsync(); this.vegaViews.set(name, vegaView); diff --git a/src/config.ts b/src/config.ts index 4aa3404f..fd214f06 100644 --- a/src/config.ts +++ b/src/config.ts @@ -44,6 +44,8 @@ export const DEFAULT_CONFIG = { heatmapHeight: null, maxCircleSize: 700, yAxisExtent: 50, + fillColor: "#4c78a8", + responsive: false, //---------- // debugging diff --git a/src/views/hbar.ts b/src/views/hbar.ts index e73da6fb..a9a23392 100644 --- a/src/views/hbar.ts +++ b/src/views/hbar.ts @@ -1,7 +1,7 @@ import { Config } from "./../config"; import { EncodeEntry, parse, Spec, View, Warn } from "vega"; import { View0D } from "../api"; -import { darkerBlue, loadingMarks } from "./histogram"; +import { loadingMarks } from "./histogram"; export function createHorizontalBarView( el: Element, @@ -91,7 +91,7 @@ export function createHorizontalBarView( encode: { enter: { ...barEnterEncodeBase, - fill: { value: darkerBlue } + fill: { value: config.fillColor } }, update: { ...barUpdateEncodeBase, diff --git a/src/views/heatmap.ts b/src/views/heatmap.ts index 91d7f22e..9fa79f13 100644 --- a/src/views/heatmap.ts +++ b/src/views/heatmap.ts @@ -1,7 +1,7 @@ import { parse, Spec, View, Mark, Warn } from "vega"; import { View2D } from "../api"; import { Config } from "../config"; -import { darkerBlue, loadingMarks } from "./histogram"; +import { loadingMarks } from "./histogram"; export function createHeatmapView( el: Element, @@ -116,7 +116,7 @@ export function createHeatmapView( encode: { enter: { shape: { value: "circle" }, - fill: { value: darkerBlue } + fill: { value: config.fillColor } }, update: { x: { @@ -570,7 +570,7 @@ export function createHeatmapView( ...(config.circleHeatmap ? { size: "size", - symbolFillColor: darkerBlue, + symbolFillColor: config.fillColor, symbolStrokeWidth: 0 } : { diff --git a/src/views/histogram.ts b/src/views/histogram.ts index 9f851d0a..61f89c24 100644 --- a/src/views/histogram.ts +++ b/src/views/histogram.ts @@ -15,8 +15,6 @@ import { View1D } from "../api"; import { Config } from "../config"; import { extent, repeatInvisible } from "../util"; -export const darkerBlue = "#4c78a8"; - export function loadingMarks(heightSignal: string, rotate = false) { return [ { @@ -213,7 +211,7 @@ export function createHistogramView( from: { data: "table" }, encode: { enter: { - fill: { value: darkerBlue } + fill: { value: config.fillColor } }, update: { opacity: { signal: "approximate ? 0.7 : 1" }, @@ -415,7 +413,17 @@ export function createHistogramView( ]; const signals: Signal[] = [ - { name: "histHeight", value: config.histogramHeight }, + // { name: "width", value: "", on: [{ events: { source: "window", type: "resize" }, update: "containerSize()[0]" }] }, + { + name: "height", + value: config.histogramHeight, + on: [ + { + events: { source: "window", type: "resize" }, + update: "containerSize()[1]" + } + ] + }, { name: "pending", value: false }, { name: "approximate", value: false }, { name: "bin", value: dimension.binConfig }, @@ -539,6 +547,16 @@ export function createHistogramView( } ]; + if (config.responsive) { + signals.push({ + name: "histHeight", + value: config.histogramHeight, + update: "height - 20" + }); + } else { + signals.push({ name: "histHeight", value: config.histogramHeight }); + } + if (config.zoom) { signals.push( ...([ @@ -646,8 +664,9 @@ export function createHistogramView( const vgSpec: Spec = { $schema: "https://vega.github.io/schema/vega/v4.0.json", - autosize: "pad", + autosize: "fit", width: config.histogramWidth, + height: config.histogramHeight, padding: 5, data: data, signals: signals, diff --git a/src/views/vbar.ts b/src/views/vbar.ts index aaf93b6d..80fe65fe 100644 --- a/src/views/vbar.ts +++ b/src/views/vbar.ts @@ -1,7 +1,7 @@ import { Config } from "./../config"; import { EncodeEntry, parse, Spec, View, Warn } from "vega"; import { View0D } from "../api"; -import { darkerBlue, loadingMarks } from "./histogram"; +import { loadingMarks } from "./histogram"; export function createVerticalBarView( el: Element, @@ -85,7 +85,7 @@ export function createVerticalBarView( name: "bar", encode: { enter: { - fill: { value: darkerBlue } + fill: { value: config.fillColor } }, update: { ...barEncodeBase,