Skip to content

Commit

Permalink
feat: mr控件拖拽实现
Browse files Browse the repository at this point in the history
  • Loading branch information
Object-d committed Jan 2, 2023
1 parent 4f0372b commit 133a902
Show file tree
Hide file tree
Showing 13 changed files with 1,241 additions and 4,194 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
node_modules
.cache
dist
.parcel-cache
3 changes: 2 additions & 1 deletion example/.npmignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.cache
dist
dist
.parcel-cache
Binary file removed example/.parcel-cache/data.mdb
Binary file not shown.
Binary file removed example/.parcel-cache/lock.mdb
Binary file not shown.
Binary file added example/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 46 additions & 3 deletions example/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,55 @@
import 'react-app-polyfill/ie11';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Thing } from '../.';
import {
Application,
Sprite,
} from "pixi.js";
import {Controls} from '../src';

const containerSize = 800

const App = () => {
const ref = React.useRef(null)
React.useEffect(() => {
const app = new Application({
width: containerSize,
height: containerSize
});
ref.current.appendChild(app.view);
const luFei = Sprite.from(
"https://img1.baidu.com/it/u=2082729884,1583333066&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=711"
);
// luFei.anchor.set(0.5); // 设置锚点,position以锚点为基础
app.stage.addChild(luFei);
luFei.position.set(300, 300);
luFei.width = 100
luFei.height = 100
console.log('选中的元素', luFei)
console.log('选中的元素.getBounds', luFei.getBounds())
console.log('选中的元素.getLocalBounds', luFei.getLocalBounds())
console.log('选中的元素.getGlobalPosition', luFei.getGlobalPosition())

setTimeout(() => {
const ctrlGraph = new Controls({
element: luFei,
cornerColor: 0xec6c00,
cornerSize: 20,
padding: 20,
cornerStyle: "square",
cornerStrokeColor: 0xec6c00,
borderColor: 0xec6c00,
transparentCorners: true,
hasBorders: true,
centeredScaling: true,
controlVisibleList: ["tr", "bl", "br", "mb", "tl", "mt", "mr", "ml"]
});
app.stage.addChild(ctrlGraph);
}, 2000);

}, [])
return (
<div>
<Thing />
<div ref={ref} style={{width: containerSize, height: containerSize}} >
</div>
);
};
Expand Down
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"devDependencies": {
"@types/react": "^16.9.11",
"@types/react-dom": "^16.8.4",
"parcel": "^2.0.0-rc.0",
"parcel": "^2.4.1",
"punycode": "^1.4.1",
"typescript": "^3.4.5"
}
}
4,859 changes: 685 additions & 4,174 deletions example/yarn.lock

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions src/control.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Graphics } from "pixi.js";
import {
ControlProps,
ControlType,
CornerStyleType,
} from "./type";
import {
cursorMap,
} from './utils'

// TODO: scaling freely
export class Control extends Graphics {
public radius: number = 0;
private pos: ControlType;
private cornerColor: number;
private cornerStrokeColor: number;
private transparentCorners: boolean;

constructor(options: ControlProps) {
super();
this.radius = options.cornerSize || 10;
this.cornerColor = options.cornerColor || 0xec6c00;
this.cornerStrokeColor = options.cornerStrokeColor || 0xffffff;
this.transparentCorners = options.transparentCorners ?? true;
this.interactive = true;
this.visible = options.visible;
this.pos = options.pos;
this.cursor = cursorMap[this.pos];

this.reRender(options.x, options.y, this.radius, options.cornerStyle);
this.on("mousedown", options.onDragStart)
.on("mouseup", options.onDragEnd)
.on("mouseupoutside", options.onDragEnd)
.on("mousemove", options.onDragMove)
}

reRender(
cpX: number,
cpY: number,
radius: number,
type: CornerStyleType = "circle"
) {
this.clear();
this.lineStyle(1, this.cornerStrokeColor);
this.beginFill(this.cornerColor, this.transparentCorners ? 0.001 : 1);
if (type === "square") {
this.drawRect(cpX - radius / 2, cpY - radius / 2, radius, radius);
} else {
this.drawCircle(cpX, cpY, radius);
}
this.endFill();
}
}
144 changes: 144 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { Graphics, Sprite } from "pixi.js";
import {
ControlConfigProps,
ControlType,
ControlsProps,
Transform,
} from "./type";
import { allControlPos, calcACoords, calcCornerCoords, calcLineCoords, getLocalPoint } from './utils';
import { Control } from "./control";
import { ACoordsProps, CornerProps } from './type';

export class Controls extends Sprite {
private coords: ACoordsProps;
private lCoords: ACoordsProps;
private cornerCoords: CornerProps;
private config: ControlConfigProps;
private padding: number;
private borderColor: number;
private element: Sprite;
private controlVisibleList: ControlType[];
private transf: Transform;
private targetSize: { width: number, height: number }
private dragging: Boolean = false;
private rendering: number = 0;

constructor(options: ControlsProps) {
super();
this.config = {
cornerColor: options.cornerColor,
cornerSize: options.cornerSize,
cornerStyle: options.cornerStyle,
transparentCorners: options.transparentCorners,
centeredScaling: options.centeredScaling
};
this.transf = {
scaleX: 1,
scaleY: 1,
signX: 1,
signY: 1,
action: "scaleX",
}
this.visible = !!options.hasBorders;
this.borderColor = options.borderColor || 0xec6c00;
this.element = options.element;
this.padding = options.padding || 0; // TODO: zoom
this.controlVisibleList = options.controlVisibleList || allControlPos;
this.coords = calcACoords(this.element)
this.lCoords = calcLineCoords(this.coords, this.padding)
this.cornerCoords = calcCornerCoords(this.lCoords, this.config.cornerSize)

const bounds = this.element.getLocalBounds();
this.targetSize = {
width: bounds.width,
height: bounds.height,
}

this.renderControls()
}

renderControls() {
this.coords = calcACoords(this.element)
this.lCoords = calcLineCoords(this.coords, this.padding)
this.cornerCoords = calcCornerCoords(this.lCoords, this.config.cornerSize)

this.renderBorder();
this.renderCorners();
}

renderBorder() {
const poly = new Graphics();
const lCoords = this.lCoords;

poly.clear();
poly.lineStyle(1, this.borderColor);
poly.beginFill(this.config.cornerColor, 0);
poly.drawPolygon([
lCoords.tl,
lCoords.tr,
lCoords.br,
lCoords.bl,
lCoords.tl
]);

poly.endFill();
this.addChild(poly);
}

onDragStart = () => {
if (!this.dragging) {
this.dragging = true
}
}

onDragMove = (event: any) => {
if (this.dragging) {
const point = event.data.global
const newPoint = getLocalPoint(this.element, this.padding, point.x, point.y)
let scaleX: number
scaleX = Math.abs(newPoint.x / this.targetSize.width);
console.log('onDragMove', newPoint.x)

if (!this.rendering) {
this.rendering = requestAnimationFrame(() => {
this.element.scale.x = scaleX
if (this.rendering) {
cancelAnimationFrame(this.rendering);
}
this.removeChildren()
this.renderControls();
this.rendering = 0;
if (scaleX) {
this.transf.scaleX = scaleX
}
})
}
}
}

onDragEnd = () => {
if (this.dragging) {
this.dragging = false
}
}

renderCorners() {
const poss = Object.keys(this.cornerCoords) as ControlType[];
const controls: any[] = poss.map((pos) => {
const control = this.cornerCoords[pos];
return new Control({
...this.config,
x: control.x,
y: control.y,
pos,
element: this.element,
visible: this.controlVisibleList.includes(pos),
onDragStart: this.onDragStart,
onDragEnd: this.onDragEnd,
onDragMove: this.onDragMove,
});
});

this.addChild(...controls);
}
}
15 changes: 0 additions & 15 deletions src/index.tsx

This file was deleted.

83 changes: 83 additions & 0 deletions src/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

export type CornerControlType = "tl" | "tr" | "br" | "bl";
export type MiddleControlType = "mr" | "mt" | "ml" | "mb";
export type ControlType = CornerControlType | MiddleControlType;

export type ControlPostionType = {
[key in ControlType]: { x: number; y: number };
};
export type CornerStyleType = "circle" | "square";

export interface ControlConfigProps {
cornerSize?: number;
cornerColor?: number;
cornerStrokeColor?: number;
cornerStyle?: CornerStyleType;
transparentCorners?: boolean;
centeredScaling?: boolean;
}

export interface ControlProps extends ControlConfigProps {
x: number;
y: number;
pos: ControlType;
element: any;
visible: boolean;
onDragStart: (event: MouseEvent) => void;
onDragMove: (event: MouseEvent) => void;
onDragEnd: (event: MouseEvent) => void;
}

export interface ControlsProps extends ControlConfigProps {
element: any;
hasBorders?: boolean;
padding?: number;
borderColor?: number;
controlVisibleList?: ControlType[];
scaleProportionally?: boolean; // TODO 按比例缩放
}

export interface Transform {
action: string; // scaleX scaleY
scaleX: number;
scaleY: number;
// corner: string;
signX: number; // x轴正负号
signY: number; // x轴正负号
}

export interface Position {
x: number;
y: number;
}

export interface ACoordsProps {
tr: Position,
br: Position,
tl: Position,
bl: Position,
}

export interface OCoordsProps extends ACoordsProps {
mt: Position;
ml: Position;
mr: Position;
mb: Position;
}

export interface CornerItemProps {
x: number;
y: number;
corner: ACoordsProps;
}

export interface CornerProps {
tr: CornerItemProps,
br: CornerItemProps,
tl: CornerItemProps,
bl: CornerItemProps,
mt: CornerItemProps;
ml: CornerItemProps;
mr: CornerItemProps;
mb: CornerItemProps;
}
Loading

0 comments on commit 133a902

Please sign in to comment.