mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
034130c02f
## Summary I used [link-inspector](https://github.com/justindhillon/link-inspector) to find a bunch of broken links in this projects documentation. Here is what I fixed: https://www.html5rocks.com/en/tutorials/canvas/hidpi/ --> https://web.dev/articles/canvas-hidipi https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts --> https://www.w3.org/TR/custom-elements/ https://github.com/facebookarchive/fixed-data-table/blob/main/src/vendor_upstream/dom/normalizeWheel.js --> https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js https://upload.wikimedia.org/wikipedia/commons/e/ee/Atom_%282%29.png --> https://upload.wikimedia.org/wikipedia/commons/1/1b/Atom.png ## Support my work I used [link-inspector](https://github.com/justindhillon/link-inspector) to find and fix this issue. If you find this PR useful, give the repo a ⭐
155 lines
3.8 KiB
JavaScript
155 lines
3.8 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import type {Interaction} from './useCanvasInteraction';
|
|
import type {Size} from './geometry';
|
|
|
|
import memoize from 'memoize-one';
|
|
|
|
import {View} from './View';
|
|
import {zeroPoint} from './geometry';
|
|
import {DPR} from '../content-views/constants';
|
|
|
|
export type ViewRefs = {
|
|
activeView: View | null,
|
|
hoveredView: View | null,
|
|
};
|
|
|
|
// hidpi canvas: https://web.dev/articles/canvas-hidipi
|
|
function configureRetinaCanvas(
|
|
canvas: HTMLCanvasElement,
|
|
height: number,
|
|
width: number,
|
|
) {
|
|
canvas.width = width * DPR;
|
|
canvas.height = height * DPR;
|
|
canvas.style.width = `${width}px`;
|
|
canvas.style.height = `${height}px`;
|
|
}
|
|
|
|
const getCanvasContext = memoize(
|
|
(
|
|
canvas: HTMLCanvasElement,
|
|
height: number,
|
|
width: number,
|
|
scaleCanvas: boolean = true,
|
|
): CanvasRenderingContext2D => {
|
|
const context = canvas.getContext('2d', {alpha: false});
|
|
if (scaleCanvas) {
|
|
configureRetinaCanvas(canvas, height, width);
|
|
|
|
// Scale all drawing operations by the dpr, so you don't have to worry about the difference.
|
|
context.scale(DPR, DPR);
|
|
}
|
|
return context;
|
|
},
|
|
);
|
|
|
|
type ResetHoveredEventFn = () => void;
|
|
|
|
/**
|
|
* Represents the canvas surface and a view heirarchy. A surface is also the
|
|
* place where all interactions enter the view heirarchy.
|
|
*/
|
|
export class Surface {
|
|
rootView: ?View;
|
|
|
|
_context: ?CanvasRenderingContext2D;
|
|
_canvasSize: ?Size;
|
|
|
|
_resetHoveredEvent: ResetHoveredEventFn;
|
|
|
|
_viewRefs: ViewRefs = {
|
|
activeView: null,
|
|
hoveredView: null,
|
|
};
|
|
|
|
constructor(resetHoveredEvent: ResetHoveredEventFn) {
|
|
this._resetHoveredEvent = resetHoveredEvent;
|
|
}
|
|
|
|
hasActiveView(): boolean {
|
|
return this._viewRefs.activeView !== null;
|
|
}
|
|
|
|
setCanvas(canvas: HTMLCanvasElement, canvasSize: Size) {
|
|
this._context = getCanvasContext(
|
|
canvas,
|
|
canvasSize.height,
|
|
canvasSize.width,
|
|
);
|
|
this._canvasSize = canvasSize;
|
|
|
|
if (this.rootView) {
|
|
this.rootView.setNeedsDisplay();
|
|
}
|
|
}
|
|
|
|
displayIfNeeded() {
|
|
const {rootView, _canvasSize, _context} = this;
|
|
if (!rootView || !_context || !_canvasSize) {
|
|
return;
|
|
}
|
|
rootView.setFrame({
|
|
origin: zeroPoint,
|
|
size: _canvasSize,
|
|
});
|
|
rootView.setVisibleArea({
|
|
origin: zeroPoint,
|
|
size: _canvasSize,
|
|
});
|
|
rootView.displayIfNeeded(_context, this._viewRefs);
|
|
}
|
|
|
|
getCurrentCursor(): string | null {
|
|
const {activeView, hoveredView} = this._viewRefs;
|
|
if (activeView !== null) {
|
|
return activeView.currentCursor;
|
|
} else if (hoveredView !== null) {
|
|
return hoveredView.currentCursor;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
handleInteraction(interaction: Interaction) {
|
|
const rootView = this.rootView;
|
|
if (rootView != null) {
|
|
const viewRefs = this._viewRefs;
|
|
switch (interaction.type) {
|
|
case 'mousemove':
|
|
case 'wheel-control':
|
|
case 'wheel-meta':
|
|
case 'wheel-plain':
|
|
case 'wheel-shift':
|
|
// Clean out the hovered view before processing this type of interaction.
|
|
const hoveredView = viewRefs.hoveredView;
|
|
viewRefs.hoveredView = null;
|
|
|
|
rootView.handleInteractionAndPropagateToSubviews(
|
|
interaction,
|
|
viewRefs,
|
|
);
|
|
|
|
// If a previously hovered view is no longer hovered, update the outer state.
|
|
if (hoveredView !== null && viewRefs.hoveredView === null) {
|
|
this._resetHoveredEvent();
|
|
}
|
|
break;
|
|
default:
|
|
rootView.handleInteractionAndPropagateToSubviews(
|
|
interaction,
|
|
viewRefs,
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|