2024-03-11 01:33:47 +08:00

104 lines
4.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ZOOM_OUT_COEFFICIENT, ZOOM_IN_COEFFICIENT, SCALE_STEP, MIN_SCALE_RATIO, MAX_SCALE_RATIO } from '../constants'
import { PixelPosition, PositionRange, TransformConfig } from '../types/common'
import { GenerateRangeOffsetConfig, InitMattingTransformConfig } from '../types/transform'
import { computeHelpers } from './init-compute'
const { sign } = Math
/** 生成表示绘制范围各个值偏移量的对象 */
export function generateRangeOffset(rangeOffsetConfig: GenerateRangeOffsetConfig): PositionRange {
const { pageX, pageY, positionRange } = rangeOffsetConfig
const { minX, maxX, minY, maxY } = positionRange
return { minX: minX - pageX, maxX: maxX - pageX, minY: minY - pageY, maxY: maxY - pageY }
}
/** 根据当前鼠标位置更新绘制范围 */
export function updateRangeByMovements(ev: MouseEvent, positionRange: PositionRange) {
const { movementX: deltaX, movementY: deltaY } = ev
positionRange.minX += deltaX
positionRange.maxX += deltaX
positionRange.minY += deltaY
positionRange.maxY += deltaY
}
/** 变换(平移、缩放)时重绘画板中图像 */
export function redrawMattingBoardsWhileScaling(ev: WheelEvent, scalingConfig: InitMattingTransformConfig) {
const { transformConfig, inputContexts: inputContext, outputContexts: outputContext } = scalingConfig
updateTransformConfigWhileScaling(ev, transformConfig)
}
/** 鼠标滚轮滚动缩放时更新变换参数 */
function updateTransformConfigWhileScaling(ev: WheelEvent, transformConfig: TransformConfig) {
const { deltaY, pageX, pageY, target } = ev
const { positionRange, scaleRatio } = transformConfig
const { left, top } = computeHelpers.computeBoardRect(target as HTMLCanvasElement)
const x = transformHelpers.computePivot(pageX, left)
const y = transformHelpers.computePivot(pageY, top)
const deltaRatio = transformHelpers.computeDeltaRatio(deltaY)
const targetScaleRatio = transformHelpers.computeNewScaleRatio(scaleRatio, deltaRatio)
transformConfig.scaleRatio = transformHelpers.computeClampedTargetScaleRatio(targetScaleRatio)
// 不能直接使用deltaRatioscaleRatio接近最大/最小值时,二者就不相等了。
const rangeScaleRatio = computeRangeScaleRatio(transformConfig.scaleRatio, scaleRatio)
transformConfig.positionRange = transformHelpers.computeNewPositionRange(positionRange, { x, y }, rangeScaleRatio)
}
/** 计算鼠标的位置对应的像素在图像中的位置 */
function computePivot(pagePivot: number, leftOrTop: number) {
return pagePivot - leftOrTop
}
/** 计算变化比率 */
function computeDeltaRatio(deltaY: number) {
const scaleCoefficient = transformHelpers.isZoomOut(deltaY) ? ZOOM_OUT_COEFFICIENT : ZOOM_IN_COEFFICIENT
return scaleCoefficient * SCALE_STEP
}
/** 是否为缩小 */
function isZoomOut(deltaY: number): boolean {
return -sign(deltaY) === ZOOM_OUT_COEFFICIENT
}
/** 计算新的缩放比率 */
function computeNewScaleRatio(scaleRatio: number, deltaRatio: number): number {
return scaleRatio + scaleRatio * deltaRatio
}
/** 计算绘制范围的变化比率 */
function computeRangeScaleRatio(newRatio: number, oldRatio: number): number {
return (newRatio - oldRatio) / oldRatio
}
/** 夹住缩放比例使其不会超出范围 */
function computeClampedTargetScaleRatio(scaleRatio: number): number {
return scaleRatio < MIN_SCALE_RATIO ? MIN_SCALE_RATIO : scaleRatio > MAX_SCALE_RATIO ? MAX_SCALE_RATIO : scaleRatio
}
/** 计算新的绘制范围 */
function computeNewPositionRange(positionRange: PositionRange, position: PixelPosition, deltaRatio: number): PositionRange {
const { x, y } = position
let { minX, maxX, minY, maxY } = positionRange
minX = transformHelpers.computeNewSingleRange(minX, x, deltaRatio)
maxX = transformHelpers.computeNewSingleRange(maxX, x, deltaRatio)
minY = transformHelpers.computeNewSingleRange(minY, y, deltaRatio)
maxY = transformHelpers.computeNewSingleRange(maxY, y, deltaRatio)
return { minX, maxX, minY, maxY }
}
/** 计算缩放后x/y轴方向的新的绘制范围值 */
function computeNewSingleRange(singleRange: number, pivot: number, deltaRatio: number): number {
const vectorDistance = singleRange - pivot
const deltaRange = vectorDistance * deltaRatio
return singleRange + deltaRange
}
export const transformHelpers = {
updateTransformConfigWhileScaling,
computePivot,
computeDeltaRatio,
isZoomOut,
computeNewScaleRatio,
computeClampedTargetScaleRatio,
computeNewPositionRange,
computeNewSingleRange,
}