Skip to content

Commit

Permalink
Merge branch 'master' into fancy-canvas-0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
Nipheris committed Nov 14, 2022
2 parents e17d80e + 1afc8db commit 4a28283
Show file tree
Hide file tree
Showing 238 changed files with 952 additions and 252 deletions.
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = [
{
name: 'ESM',
path: 'dist/lightweight-charts.esm.production.js',
limit: '43.6 KB',
limit: '43.9 KB',
},
{
name: 'Standalone',
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
"eslint-plugin-markdown": "~3.0.0",
"eslint-plugin-mdx": "~1.17.0",
"eslint-plugin-prefer-arrow": "~1.2.3",
"eslint-plugin-react": "~7.30.1",
"eslint-plugin-tsdoc": "~0.2.16",
"eslint-plugin-unicorn": "~40.1.0",
"eslint-plugin-react": "~7.30.1",
"express": "~4.18.1",
"glob": "~8.0.3",
"markdown-it": "~13.0.1",
Expand All @@ -83,7 +83,8 @@
"tslint-eslint-rules": "~5.4.0",
"tslint-microsoft-contrib": "~6.2.0",
"ttypescript": "~1.5.13",
"typescript": "4.7.3"
"typescript": "4.7.3",
"yargs": "~17.6.0"
},
"scripts": {
"postinstall": "npm run install-hooks",
Expand Down
4 changes: 4 additions & 0 deletions src/api/options/series-options-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,23 @@ export const lineStyleDefaults: LineStyleOptions = {
crosshairMarkerVisible: true,
crosshairMarkerRadius: 4,
crosshairMarkerBorderColor: '',
crosshairMarkerBorderWidth: 2,
crosshairMarkerBackgroundColor: '',
lastPriceAnimation: LastPriceAnimationMode.Disabled,
};

export const areaStyleDefaults: AreaStyleOptions = {
topColor: 'rgba( 46, 220, 135, 0.4)',
bottomColor: 'rgba( 40, 221, 100, 0)',
invertFilledArea: false,
lineColor: '#33D778',
lineStyle: LineStyle.Solid,
lineWidth: 3,
lineType: LineType.Simple,
crosshairMarkerVisible: true,
crosshairMarkerRadius: 4,
crosshairMarkerBorderColor: '',
crosshairMarkerBorderWidth: 2,
crosshairMarkerBackgroundColor: '',
lastPriceAnimation: LastPriceAnimationMode.Disabled,
};
Expand All @@ -78,6 +81,7 @@ export const baselineStyleDefaults: BaselineStyleOptions = {
crosshairMarkerVisible: true,
crosshairMarkerRadius: 4,
crosshairMarkerBorderColor: '',
crosshairMarkerBorderWidth: 2,
crosshairMarkerBackgroundColor: '',

lastPriceAnimation: LastPriceAnimationMode.Disabled,
Expand Down
51 changes: 32 additions & 19 deletions src/gui/chart-widget.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Size, size } from 'fancy-canvas';

import { ensureDefined, ensureNotNull } from '../helpers/assertions';
import { isChromiumBased, isWindows } from '../helpers/browsers';
import { Delegate } from '../helpers/delegate';
import { IDestroyable } from '../helpers/idestroyable';
import { ISubscription } from '../helpers/isubscription';
Expand Down Expand Up @@ -35,6 +36,8 @@ export interface MouseEventParamsImpl {

export type MouseEventParamsImplSupplier = () => MouseEventParamsImpl;

const windowsChrome = isChromiumBased() && isWindows();

export class ChartWidget implements IDestroyable {
private readonly _options: ChartOptionsInternal;
private _paneWidgets: PaneWidget[] = [];
Expand Down Expand Up @@ -457,31 +460,41 @@ export class ChartWidget implements IDestroyable {
this._element.removeEventListener('wheel', this._onWheelBound);
}

private _onMousewheel(event: WheelEvent): void {
let deltaX = event.deltaX / 100;
let deltaY = -(event.deltaY / 100);
private _determineWheelSpeedAdjustment(event: WheelEvent): number {
switch (event.deltaMode) {
case event.DOM_DELTA_PAGE:
// one screen at time scroll mode
return 120;
case event.DOM_DELTA_LINE:
// one line at time scroll mode
return 32;
}

if ((deltaX === 0 || !this._options.handleScroll.mouseWheel) &&
(deltaY === 0 || !this._options.handleScale.mouseWheel)) {
return;
if (!windowsChrome) {
return 1;
}

if (event.cancelable) {
event.preventDefault();
// Chromium on Windows has a bug where the scroll speed isn't correctly
// adjusted for high density displays. We need to correct for this so that
// scroll speed is consistent between browsers.
// https://bugs.chromium.org/p/chromium/issues/detail?id=1001735
// https://bugs.chromium.org/p/chromium/issues/detail?id=1207308
return (1 / window.devicePixelRatio);
}

private _onMousewheel(event: WheelEvent): void {
if ((event.deltaX === 0 || !this._options.handleScroll.mouseWheel) &&
(event.deltaY === 0 || !this._options.handleScale.mouseWheel)) {
return;
}

switch (event.deltaMode) {
case event.DOM_DELTA_PAGE:
// one screen at time scroll mode
deltaX *= 120;
deltaY *= 120;
break;
const scrollSpeedAdjustment = this._determineWheelSpeedAdjustment(event);

case event.DOM_DELTA_LINE:
// one line at time scroll mode
deltaX *= 32;
deltaY *= 32;
break;
const deltaX = scrollSpeedAdjustment * event.deltaX / 100;
const deltaY = -(scrollSpeedAdjustment * event.deltaY / 100);

if (event.cancelable) {
event.preventDefault();
}

if (deltaY !== 0 && this._options.handleScale.mouseWheel) {
Expand Down
28 changes: 24 additions & 4 deletions src/gui/price-axis-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,21 @@ export class PriceAxisWidget implements IDestroyable {
// crosshair individually
updateForSources(orderedSources);

views.forEach((view: IPriceAxisView) => view.setFixedCoordinate(view.coordinate()));

const options = this._priceScale.options();
if (!options.alignLabels) {
return;
}

this._fixLabelOverlap(views, rendererOptions, center);
}

private _fixLabelOverlap(views: IPriceAxisView[], rendererOptions: Readonly<PriceAxisViewRendererOptions>, center: number): void {
if (this._size === null) {
return;
}

// split into two parts
const top = views.filter((view: IPriceAxisView) => view.coordinate() <= center);
const bottom = views.filter((view: IPriceAxisView) => view.coordinate() > center);
Expand All @@ -540,11 +555,16 @@ export class PriceAxisWidget implements IDestroyable {

bottom.sort((l: IPriceAxisView, r: IPriceAxisView) => l.coordinate() - r.coordinate());

views.forEach((view: IPriceAxisView) => view.setFixedCoordinate(view.coordinate()));
for (const view of views) {
const halfHeight = Math.floor(view.height(rendererOptions) / 2);
const coordinate = view.coordinate();
if (coordinate > -halfHeight && coordinate < halfHeight) {
view.setFixedCoordinate(halfHeight);
}

const options = this._priceScale.options();
if (!options.alignLabels) {
return;
if (coordinate > (this._size.height - halfHeight) && coordinate < this._size.height + halfHeight) {
view.setFixedCoordinate(this._size.height - halfHeight);
}
}

for (let i = 1; i < top.length; i++) {
Expand Down
20 changes: 20 additions & 0 deletions src/helpers/browsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,23 @@ export function isChrome(): boolean {
return window.chrome !== undefined;
}

// Determine whether the browser is running on windows.
export function isWindows(): boolean {
// more accurate if available
if (
navigator?.userAgentData?.platform
) {
return navigator.userAgentData.platform === 'Windows';
}
return navigator.userAgent.toLowerCase().indexOf('win') >= 0;
}

// Determine whether the browser is Chromium based.
export function isChromiumBased(): boolean {
if (!navigator.userAgentData) { return false; }
return navigator.userAgentData.brands.some(
(brand: UADataBrand) => {
return brand.brand.includes('Chromium');
}
);
}
25 changes: 25 additions & 0 deletions src/model/series-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ export interface LineStyleOptions {
* @defaultValue `''`
*/
crosshairMarkerBackgroundColor: string;
/**
* Crosshair marker border width in pixels.
*
* @defaultValue `2`
*/
crosshairMarkerBorderWidth: number;

/**
* Last price animation mode.
Expand Down Expand Up @@ -225,6 +231,13 @@ export interface AreaStyleOptions {
*/
bottomColor: string;

/**
* Invert the filled area. Fills the area above the line if set to true.
*
* @defaultValue `false`
*/
invertFilledArea: boolean;

/**
* Line color.
*
Expand Down Expand Up @@ -277,6 +290,12 @@ export interface AreaStyleOptions {
* @defaultValue `''`
*/
crosshairMarkerBackgroundColor: string;
/**
* Crosshair marker border width in pixels.
*
* @defaultValue `2`
*/
crosshairMarkerBorderWidth: number;

/**
* Last price animation mode.
Expand Down Expand Up @@ -398,6 +417,12 @@ export interface BaselineStyleOptions {
* @defaultValue `''`
*/
crosshairMarkerBackgroundColor: string;
/**
* Crosshair marker border width in pixels.
*
* @defaultValue `2`
*/
crosshairMarkerBorderWidth: number;

/**
* Last price animation mode.
Expand Down
15 changes: 14 additions & 1 deletion src/model/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export interface MarkerData {
price: BarPrice;
radius: number;
borderColor: string | null;
borderWidth: number;
backgroundColor: string;
}

Expand Down Expand Up @@ -453,8 +454,9 @@ export class Series<T extends SeriesType = SeriesType> extends PriceDataSource i
const price = bar.value[PlotRowValueIndex.Close] as BarPrice;
const radius = this._markerRadius();
const borderColor = this._markerBorderColor();
const borderWidth = this._markerBorderWidth();
const backgroundColor = this._markerBackgroundColor(index);
return { price, radius, borderColor, backgroundColor };
return { price, radius, borderColor, borderWidth, backgroundColor };
}

public title(): string {
Expand Down Expand Up @@ -520,6 +522,17 @@ export class Series<T extends SeriesType = SeriesType> extends PriceDataSource i
return null;
}

private _markerBorderWidth(): number {
switch (this._seriesType) {
case 'Line':
case 'Area':
case 'Baseline':
return (this._options as (LineStyleOptions | AreaStyleOptions | BaselineStyleOptions)).crosshairMarkerBorderWidth;
}

return 0;
}

private _markerBackgroundColor(index: TimePointIndex): string {
switch (this._seriesType) {
case 'Line':
Expand Down
5 changes: 4 additions & 1 deletion src/renderers/area-renderer-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface PaneRendererAreaDataBase<TItem extends AreaFillItemBase = AreaF
lineStyle: LineStyle;

baseLevelCoordinate: Coordinate | null;
invertFilledArea: boolean;

barWidth: number;

Expand Down Expand Up @@ -49,7 +50,9 @@ export abstract class PaneRendererAreaBase<TData extends PaneRendererAreaDataBas
}

const { items, visibleRange, barWidth, lineWidth, lineStyle, lineType } = this._data;
const baseLevelCoordinate = this._data.baseLevelCoordinate ?? renderingScope.mediaSize.height as Coordinate;
const baseLevelCoordinate =
this._data.baseLevelCoordinate ??
(this._data.invertFilledArea ? 0 : renderingScope.mediaSize.height) as Coordinate;

if (visibleRange === null) {
return;
Expand Down
7 changes: 5 additions & 2 deletions src/renderers/marks-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MediaCoordinatesPaneRenderer } from './media-coordinates-pane-renderer'
export interface MarksRendererData {
items: LineItemBase[];
lineColor: string;
lineWidth: number;
backColor: string;
radius: number;
visibleRange: SeriesItemsIndexesRange | null;
Expand Down Expand Up @@ -40,8 +41,10 @@ export class PaneRendererMarks extends MediaCoordinatesPaneRenderer {
ctx.fill();
};

ctx.fillStyle = data.backColor;
draw(data.radius + 2);
if (data.lineWidth > 0) {
ctx.fillStyle = data.backColor;
draw(data.radius + data.lineWidth);
}

ctx.fillStyle = data.lineColor;
draw(data.radius);
Expand Down
17 changes: 17 additions & 0 deletions src/typings/dom-not-standarted/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ interface UIEvent {
sourceCapabilities?: InputDeviceCapabilities;
}

/**
* Navigator userAgentData
* https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData
* More reliable way of determining chromium browsers.
* Note: This is a partial type definition for the low entropy properties.
*/
interface UADataBrand {
brand: string; version: string;
}
interface Navigator {
userAgentData?: {
brands: UADataBrand[];
platform: string;
mobile: boolean;
};
}

interface Window {
chrome: unknown;
}
1 change: 1 addition & 0 deletions src/views/pane/area-pane-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class SeriesAreaPaneView extends LinePaneViewBase<'Area', AreaFillItem &
lineStyle: areaStyleProperties.lineStyle,
lineWidth: areaStyleProperties.lineWidth,
baseLevelCoordinate: null,
invertFilledArea: areaStyleProperties.invertFilledArea,
visibleRange: this._itemsVisibleRange,
barWidth: this._model.timeScale().barSpacing(),
});
Expand Down
1 change: 1 addition & 0 deletions src/views/pane/baseline-pane-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class SeriesBaselinePaneView extends LinePaneViewBase<'Baseline', Baselin
lineType: baselineProps.lineType,

baseLevelCoordinate,
invertFilledArea: false,

visibleRange: this._itemsVisibleRange,
barWidth,
Expand Down
2 changes: 2 additions & 0 deletions src/views/pane/crosshair-marks-pane-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function createEmptyMarkerData(): MarksRendererData {
lineColor: '',
backColor: '',
radius: 0,
lineWidth: 0,
visibleRange: null,
};
}
Expand Down Expand Up @@ -84,6 +85,7 @@ export class CrosshairMarksPaneView implements IUpdatablePaneView {
const firstValue = ensureNotNull(s.firstValue());
data.lineColor = seriesData.backgroundColor;
data.radius = seriesData.radius;
data.lineWidth = seriesData.borderWidth;
data.items[0].price = seriesData.price;
data.items[0].y = s.priceScale().priceToCoordinate(seriesData.price, firstValue.value);
data.backColor = seriesData.borderColor ?? this._chartModel.backgroundColorAtYPercentFromTop(data.items[0].y / s.priceScale().height());
Expand Down
Loading

0 comments on commit 4a28283

Please sign in to comment.