21 changed files with 3762 additions and 905 deletions
@ -0,0 +1 @@ |
|||||||
|
[1214/094922.722:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3) |
@ -0,0 +1,836 @@ |
|||||||
|
export class Charm { |
||||||
|
constructor(renderingEngine = PIXI) { |
||||||
|
|
||||||
|
if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using charm.js"); |
||||||
|
|
||||||
|
//Find out which rendering engine is being used (the default is Pixi)
|
||||||
|
this.renderer = ""; |
||||||
|
|
||||||
|
//If the `renderingEngine` is Pixi, set up Pixi object aliases
|
||||||
|
if (renderingEngine.ParticleContainer && renderingEngine.Sprite) { |
||||||
|
this.renderer = "pixi"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//An array to store the global tweens
|
||||||
|
this.globalTweens = []; |
||||||
|
|
||||||
|
//An object that stores all the easing formulas
|
||||||
|
this.easingFormulas = { |
||||||
|
|
||||||
|
//Linear
|
||||||
|
linear(x) { |
||||||
|
return x; |
||||||
|
}, |
||||||
|
|
||||||
|
//Smoothstep
|
||||||
|
smoothstep(x) { |
||||||
|
return x * x * (3 - 2 * x); |
||||||
|
}, |
||||||
|
smoothstepSquared(x) { |
||||||
|
return Math.pow((x * x * (3 - 2 * x)), 2); |
||||||
|
}, |
||||||
|
smoothstepCubed(x) { |
||||||
|
return Math.pow((x * x * (3 - 2 * x)), 3); |
||||||
|
}, |
||||||
|
|
||||||
|
//Acceleration
|
||||||
|
acceleration(x) { |
||||||
|
return x * x; |
||||||
|
}, |
||||||
|
accelerationCubed(x) { |
||||||
|
return Math.pow(x * x, 3); |
||||||
|
}, |
||||||
|
|
||||||
|
//Deceleration
|
||||||
|
deceleration(x) { |
||||||
|
return 1 - Math.pow(1 - x, 2); |
||||||
|
}, |
||||||
|
decelerationCubed(x) { |
||||||
|
return 1 - Math.pow(1 - x, 3); |
||||||
|
}, |
||||||
|
|
||||||
|
//Sine
|
||||||
|
sine(x) { |
||||||
|
return Math.sin(x * Math.PI / 2); |
||||||
|
}, |
||||||
|
sineSquared(x) { |
||||||
|
return Math.pow(Math.sin(x * Math.PI / 2), 2); |
||||||
|
}, |
||||||
|
sineCubed(x) { |
||||||
|
return Math.pow(Math.sin(x * Math.PI / 2), 2); |
||||||
|
}, |
||||||
|
inverseSine(x) { |
||||||
|
return 1 - Math.sin((1 - x) * Math.PI / 2); |
||||||
|
}, |
||||||
|
inverseSineSquared(x) { |
||||||
|
return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 2); |
||||||
|
}, |
||||||
|
inverseSineCubed(x) { |
||||||
|
return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 3); |
||||||
|
}, |
||||||
|
|
||||||
|
//Spline
|
||||||
|
spline(t, p0, p1, p2, p3) { |
||||||
|
return 0.5 * ( |
||||||
|
(2 * p1) + |
||||||
|
(-p0 + p2) * t + |
||||||
|
(2 * p0 - 5 * p1 + 4 * p2 - p3) * t * t + |
||||||
|
(-p0 + 3 * p1 - 3 * p2 + p3) * t * t * t |
||||||
|
); |
||||||
|
}, |
||||||
|
|
||||||
|
//Bezier curve
|
||||||
|
cubicBezier(t, a, b, c, d) { |
||||||
|
let t2 = t * t; |
||||||
|
let t3 = t2 * t; |
||||||
|
return a + (-a * 3 + t * (3 * a - a * t)) * t + (3 * b + t * (-6 * b + b * 3 * t)) * t + (c * 3 - c * 3 * t) * t2 + d * t3; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Add `scaleX` and `scaleY` properties to Pixi sprites
|
||||||
|
this._addScaleProperties = (sprite) => { |
||||||
|
if (this.renderer === "pixi") { |
||||||
|
if (!("scaleX" in sprite) && ("scale" in sprite) && ("x" in sprite.scale)) { |
||||||
|
Object.defineProperty( |
||||||
|
sprite, |
||||||
|
"scaleX", { |
||||||
|
get() { |
||||||
|
return sprite.scale.x |
||||||
|
}, |
||||||
|
set(value) { |
||||||
|
sprite.scale.x = value |
||||||
|
} |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
if (!("scaleY" in sprite) && ("scale" in sprite) && ("y" in sprite.scale)) { |
||||||
|
Object.defineProperty( |
||||||
|
sprite, |
||||||
|
"scaleY", { |
||||||
|
get() { |
||||||
|
return sprite.scale.y |
||||||
|
}, |
||||||
|
set(value) { |
||||||
|
sprite.scale.y = value |
||||||
|
} |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
//The low level `tweenProperty` function is used as the foundation
|
||||||
|
//for the the higher level tween methods.
|
||||||
|
tweenProperty( |
||||||
|
sprite, //Sprite object
|
||||||
|
property, //String property
|
||||||
|
startValue, //Tween start value
|
||||||
|
endValue, //Tween end value
|
||||||
|
totalFrames, //Duration in frames
|
||||||
|
type = "smoothstep", //The easing type
|
||||||
|
yoyo = false, //Yoyo?
|
||||||
|
delayBeforeRepeat = 0 //Delay in frames before repeating
|
||||||
|
) { |
||||||
|
|
||||||
|
//Create the tween object
|
||||||
|
let o = {}; |
||||||
|
|
||||||
|
//If the tween is a bounce type (a spline), set the
|
||||||
|
//start and end magnitude values
|
||||||
|
let typeArray = type.split(" "); |
||||||
|
if (typeArray[0] === "bounce") { |
||||||
|
o.startMagnitude = parseInt(typeArray[1]); |
||||||
|
o.endMagnitude = parseInt(typeArray[2]); |
||||||
|
} |
||||||
|
|
||||||
|
//Use `o.start` to make a new tween using the current
|
||||||
|
//end point values
|
||||||
|
o.start = (startValue, endValue) => { |
||||||
|
|
||||||
|
//Clone the start and end values so that any possible references to sprite
|
||||||
|
//properties are converted to ordinary numbers
|
||||||
|
o.startValue = JSON.parse(JSON.stringify(startValue)); |
||||||
|
o.endValue = JSON.parse(JSON.stringify(endValue)); |
||||||
|
o.playing = true; |
||||||
|
o.totalFrames = totalFrames; |
||||||
|
o.frameCounter = 0; |
||||||
|
|
||||||
|
//Add the tween to the global `tweens` array. The `tweens` array is
|
||||||
|
//updated on each frame
|
||||||
|
this.globalTweens.push(o); |
||||||
|
}; |
||||||
|
|
||||||
|
//Call `o.start` to start the tween
|
||||||
|
o.start(startValue, endValue); |
||||||
|
|
||||||
|
//The `update` method will be called on each frame by the game loop.
|
||||||
|
//This is what makes the tween move
|
||||||
|
o.update = () => { |
||||||
|
|
||||||
|
let time, curvedTime; |
||||||
|
|
||||||
|
if (o.playing) { |
||||||
|
|
||||||
|
//If the elapsed frames are less than the total frames,
|
||||||
|
//use the tweening formulas to move the sprite
|
||||||
|
if (o.frameCounter < o.totalFrames) { |
||||||
|
|
||||||
|
//Find the normalized value
|
||||||
|
let normalizedTime = o.frameCounter / o.totalFrames; |
||||||
|
|
||||||
|
//Select the correct easing function from the
|
||||||
|
//`ease` object’s library of easing functions
|
||||||
|
|
||||||
|
|
||||||
|
//If it's not a spline, use one of the ordinary easing functions
|
||||||
|
if (typeArray[0] !== "bounce") { |
||||||
|
curvedTime = this.easingFormulas[type](normalizedTime); |
||||||
|
} |
||||||
|
|
||||||
|
//If it's a spline, use the `spline` function and apply the
|
||||||
|
//2 additional `type` array values as the spline's start and
|
||||||
|
//end points
|
||||||
|
else { |
||||||
|
curvedTime = this.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude); |
||||||
|
} |
||||||
|
|
||||||
|
//Interpolate the sprite's property based on the curve
|
||||||
|
sprite[property] = (o.endValue * curvedTime) + (o.startValue * (1 - curvedTime)); |
||||||
|
|
||||||
|
o.frameCounter += 1; |
||||||
|
} |
||||||
|
|
||||||
|
//When the tween has finished playing, run the end tasks
|
||||||
|
else { |
||||||
|
sprite[property] = o.endValue; |
||||||
|
o.end(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//The `end` method will be called when the tween is finished
|
||||||
|
o.end = () => { |
||||||
|
|
||||||
|
//Set `playing` to `false`
|
||||||
|
o.playing = false; |
||||||
|
|
||||||
|
//Call the tween's `onComplete` method, if it's been assigned
|
||||||
|
if (o.onComplete) o.onComplete(); |
||||||
|
|
||||||
|
//Remove the tween from the `tweens` array
|
||||||
|
this.globalTweens.splice(this.globalTweens.indexOf(o), 1); |
||||||
|
|
||||||
|
//If the tween's `yoyo` property is `true`, create a new tween
|
||||||
|
//using the same values, but use the current tween's `startValue`
|
||||||
|
//as the next tween's `endValue`
|
||||||
|
if (yoyo) { |
||||||
|
this.wait(delayBeforeRepeat).then(() => { |
||||||
|
o.start(o.endValue, o.startValue); |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Pause and play methods
|
||||||
|
o.play = () => o.playing = true; |
||||||
|
o.pause = () => o.playing = false; |
||||||
|
|
||||||
|
//Return the tween object
|
||||||
|
return o; |
||||||
|
} |
||||||
|
|
||||||
|
//`makeTween` is a general low-level method for making complex tweens
|
||||||
|
//out of multiple `tweenProperty` functions. Its one argument,
|
||||||
|
//`tweensToAdd` is an array containing multiple `tweenProperty` calls
|
||||||
|
|
||||||
|
makeTween(tweensToAdd) { |
||||||
|
|
||||||
|
//Create an object to manage the tweens
|
||||||
|
let o = {}; |
||||||
|
|
||||||
|
//Create a `tweens` array to store the new tweens
|
||||||
|
o.tweens = []; |
||||||
|
|
||||||
|
//Make a new tween for each array
|
||||||
|
tweensToAdd.forEach(tweenPropertyArguments => { |
||||||
|
|
||||||
|
//Use the tween property arguments to make a new tween
|
||||||
|
let newTween = this.tweenProperty(...tweenPropertyArguments); |
||||||
|
|
||||||
|
//Push the new tween into this object's internal `tweens` array
|
||||||
|
o.tweens.push(newTween); |
||||||
|
}); |
||||||
|
|
||||||
|
//Add a counter to keep track of the
|
||||||
|
//number of tweens that have completed their actions
|
||||||
|
let completionCounter = 0; |
||||||
|
|
||||||
|
//`o.completed` will be called each time one of the tweens
|
||||||
|
//finishes
|
||||||
|
o.completed = () => { |
||||||
|
|
||||||
|
//Add 1 to the `completionCounter`
|
||||||
|
completionCounter += 1; |
||||||
|
|
||||||
|
//If all tweens have finished, call the user-defined `onComplete`
|
||||||
|
//method, if it's been assigned. Reset the `completionCounter`
|
||||||
|
if (completionCounter === o.tweens.length) { |
||||||
|
if (o.onComplete) o.onComplete(); |
||||||
|
completionCounter = 0; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Add `onComplete` methods to all tweens
|
||||||
|
o.tweens.forEach(tween => { |
||||||
|
tween.onComplete = () => o.completed(); |
||||||
|
}); |
||||||
|
|
||||||
|
//Add pause and play methods to control all the tweens
|
||||||
|
o.pause = () => { |
||||||
|
o.tweens.forEach(tween => { |
||||||
|
tween.playing = false; |
||||||
|
}); |
||||||
|
}; |
||||||
|
o.play = () => { |
||||||
|
o.tweens.forEach(tween => { |
||||||
|
tween.playing = true; |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
//Return the tween object
|
||||||
|
return o; |
||||||
|
} |
||||||
|
|
||||||
|
/* High level tween methods */ |
||||||
|
|
||||||
|
//1. Simple tweens
|
||||||
|
|
||||||
|
//`fadeOut`
|
||||||
|
fadeOut(sprite, frames = 60) { |
||||||
|
return this.tweenProperty( |
||||||
|
sprite, "alpha", sprite.alpha, 0, frames, "sine" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
//`fadeIn`
|
||||||
|
fadeIn(sprite, frames = 60) { |
||||||
|
return this.tweenProperty( |
||||||
|
sprite, "alpha", sprite.alpha, 1, frames, "sine" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
//`pulse`
|
||||||
|
//Fades the sprite in and out at a steady rate.
|
||||||
|
//Set the `minAlpha` to something greater than 0 if you
|
||||||
|
//don't want the sprite to fade away completely
|
||||||
|
pulse(sprite, frames = 60, minAlpha = 0) { |
||||||
|
return this.tweenProperty( |
||||||
|
sprite, "alpha", sprite.alpha, minAlpha, frames, "smoothstep", true |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
//2. Complex tweens
|
||||||
|
|
||||||
|
slide( |
||||||
|
sprite, endX, endY, |
||||||
|
frames = 60, type = "smoothstep", yoyo = false, delayBeforeRepeat = 0 |
||||||
|
) { |
||||||
|
return this.makeTween([ |
||||||
|
|
||||||
|
//Create the x axis tween
|
||||||
|
[sprite, "x", sprite.x, endX, frames, type, yoyo, delayBeforeRepeat], |
||||||
|
|
||||||
|
//Create the y axis tween
|
||||||
|
[sprite, "y", sprite.y, endY, frames, type, yoyo, delayBeforeRepeat] |
||||||
|
|
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
breathe( |
||||||
|
sprite, endScaleX = 0.8, endScaleY = 0.8, |
||||||
|
frames = 60, yoyo = true, delayBeforeRepeat = 0 |
||||||
|
) { |
||||||
|
|
||||||
|
//Add `scaleX` and `scaleY` properties to Pixi sprites
|
||||||
|
this._addScaleProperties(sprite); |
||||||
|
|
||||||
|
return this.makeTween([ |
||||||
|
|
||||||
|
//Create the scaleX tween
|
||||||
|
[ |
||||||
|
sprite, "scaleX", sprite.scaleX, endScaleX, |
||||||
|
frames, "smoothstepSquared", yoyo, delayBeforeRepeat |
||||||
|
], |
||||||
|
|
||||||
|
//Create the scaleY tween
|
||||||
|
[ |
||||||
|
sprite, "scaleY", sprite.scaleY, endScaleY, |
||||||
|
frames, "smoothstepSquared", yoyo, delayBeforeRepeat |
||||||
|
] |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
scale(sprite, endScaleX = 0.5, endScaleY = 0.5, frames = 60) { |
||||||
|
|
||||||
|
//Add `scaleX` and `scaleY` properties to Pixi sprites
|
||||||
|
this._addScaleProperties(sprite); |
||||||
|
|
||||||
|
return this.makeTween([ |
||||||
|
|
||||||
|
//Create the scaleX tween
|
||||||
|
[ |
||||||
|
sprite, "scaleX", sprite.scaleX, endScaleX, |
||||||
|
frames, "smoothstep", false |
||||||
|
], |
||||||
|
|
||||||
|
//Create the scaleY tween
|
||||||
|
[ |
||||||
|
sprite, "scaleY", sprite.scaleY, endScaleY, |
||||||
|
frames, "smoothstep", false |
||||||
|
] |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
strobe( |
||||||
|
sprite, scaleFactor = 1.3, startMagnitude = 10, endMagnitude = 20, |
||||||
|
frames = 10, yoyo = true, delayBeforeRepeat = 0 |
||||||
|
) { |
||||||
|
|
||||||
|
let bounce = "bounce " + startMagnitude + " " + endMagnitude; |
||||||
|
|
||||||
|
//Add `scaleX` and `scaleY` properties to Pixi sprites
|
||||||
|
this._addScaleProperties(sprite); |
||||||
|
|
||||||
|
return this.makeTween([ |
||||||
|
|
||||||
|
//Create the scaleX tween
|
||||||
|
[ |
||||||
|
sprite, "scaleX", sprite.scaleX, scaleFactor, frames, |
||||||
|
bounce, yoyo, delayBeforeRepeat |
||||||
|
], |
||||||
|
|
||||||
|
//Create the scaleY tween
|
||||||
|
[ |
||||||
|
sprite, "scaleY", sprite.scaleY, scaleFactor, frames, |
||||||
|
bounce, yoyo, delayBeforeRepeat |
||||||
|
] |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
wobble( |
||||||
|
sprite, |
||||||
|
scaleFactorX = 1.2, |
||||||
|
scaleFactorY = 1.2, |
||||||
|
frames = 10, |
||||||
|
xStartMagnitude = 10, |
||||||
|
xEndMagnitude = 10, |
||||||
|
yStartMagnitude = -10, |
||||||
|
yEndMagnitude = -10, |
||||||
|
friction = 0.98, |
||||||
|
yoyo = true, |
||||||
|
delayBeforeRepeat = 0 |
||||||
|
) { |
||||||
|
|
||||||
|
let bounceX = "bounce " + xStartMagnitude + " " + xEndMagnitude; |
||||||
|
let bounceY = "bounce " + yStartMagnitude + " " + yEndMagnitude; |
||||||
|
|
||||||
|
//Add `scaleX` and `scaleY` properties to Pixi sprites
|
||||||
|
this._addScaleProperties(sprite); |
||||||
|
|
||||||
|
let o = this.makeTween([ |
||||||
|
|
||||||
|
//Create the scaleX tween
|
||||||
|
[ |
||||||
|
sprite, "scaleX", sprite.scaleX, scaleFactorX, frames, |
||||||
|
bounceX, yoyo, delayBeforeRepeat |
||||||
|
], |
||||||
|
|
||||||
|
//Create the scaleY tween
|
||||||
|
[ |
||||||
|
sprite, "scaleY", sprite.scaleY, scaleFactorY, frames, |
||||||
|
bounceY, yoyo, delayBeforeRepeat |
||||||
|
] |
||||||
|
]); |
||||||
|
|
||||||
|
//Add some friction to the `endValue` at the end of each tween
|
||||||
|
o.tweens.forEach(tween => { |
||||||
|
tween.onComplete = () => { |
||||||
|
|
||||||
|
//Add friction if the `endValue` is greater than 1
|
||||||
|
if (tween.endValue > 1) { |
||||||
|
tween.endValue *= friction; |
||||||
|
|
||||||
|
//Set the `endValue` to 1 when the effect is finished and
|
||||||
|
//remove the tween from the global `tweens` array
|
||||||
|
if (tween.endValue <= 1) { |
||||||
|
tween.endValue = 1; |
||||||
|
this.removeTween(tween); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
return o; |
||||||
|
} |
||||||
|
|
||||||
|
//3. Motion path tweens
|
||||||
|
|
||||||
|
followCurve( |
||||||
|
sprite, |
||||||
|
pointsArray, |
||||||
|
totalFrames, |
||||||
|
type = "smoothstep", |
||||||
|
yoyo = false, |
||||||
|
delayBeforeRepeat = 0 |
||||||
|
) { |
||||||
|
|
||||||
|
//Create the tween object
|
||||||
|
let o = {}; |
||||||
|
|
||||||
|
//If the tween is a bounce type (a spline), set the
|
||||||
|
//start and end magnitude values
|
||||||
|
let typeArray = type.split(" "); |
||||||
|
if (typeArray[0] === "bounce") { |
||||||
|
o.startMagnitude = parseInt(typeArray[1]); |
||||||
|
o.endMagnitude = parseInt(typeArray[2]); |
||||||
|
} |
||||||
|
|
||||||
|
//Use `tween.start` to make a new tween using the current
|
||||||
|
//end point values
|
||||||
|
o.start = (pointsArray) => { |
||||||
|
o.playing = true; |
||||||
|
o.totalFrames = totalFrames; |
||||||
|
o.frameCounter = 0; |
||||||
|
|
||||||
|
//Clone the points array
|
||||||
|
o.pointsArray = JSON.parse(JSON.stringify(pointsArray)); |
||||||
|
|
||||||
|
//Add the tween to the `globalTweens` array. The `globalTweens` array is
|
||||||
|
//updated on each frame
|
||||||
|
this.globalTweens.push(o); |
||||||
|
}; |
||||||
|
|
||||||
|
//Call `tween.start` to start the first tween
|
||||||
|
o.start(pointsArray); |
||||||
|
|
||||||
|
//The `update` method will be called on each frame by the game loop.
|
||||||
|
//This is what makes the tween move
|
||||||
|
o.update = () => { |
||||||
|
|
||||||
|
let normalizedTime, curvedTime, |
||||||
|
p = o.pointsArray; |
||||||
|
|
||||||
|
if (o.playing) { |
||||||
|
|
||||||
|
//If the elapsed frames are less than the total frames,
|
||||||
|
//use the tweening formulas to move the sprite
|
||||||
|
if (o.frameCounter < o.totalFrames) { |
||||||
|
|
||||||
|
//Find the normalized value
|
||||||
|
normalizedTime = o.frameCounter / o.totalFrames; |
||||||
|
|
||||||
|
//Select the correct easing function
|
||||||
|
|
||||||
|
//If it's not a spline, use one of the ordinary tween
|
||||||
|
//functions
|
||||||
|
if (typeArray[0] !== "bounce") { |
||||||
|
curvedTime = this.easingFormulas[type](normalizedTime); |
||||||
|
} |
||||||
|
|
||||||
|
//If it's a spline, use the `spline` function and apply the
|
||||||
|
//2 additional `type` array values as the spline's start and
|
||||||
|
//end points
|
||||||
|
else { |
||||||
|
//curve = tweenFunction.spline(n, type[1], 0, 1, type[2]);
|
||||||
|
curvedTime = this.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude); |
||||||
|
} |
||||||
|
|
||||||
|
//Apply the Bezier curve to the sprite's position
|
||||||
|
sprite.x = this.easingFormulas.cubicBezier(curvedTime, p[0][0], p[1][0], p[2][0], p[3][0]); |
||||||
|
sprite.y = this.easingFormulas.cubicBezier(curvedTime, p[0][1], p[1][1], p[2][1], p[3][1]); |
||||||
|
|
||||||
|
//Add one to the `elapsedFrames`
|
||||||
|
o.frameCounter += 1; |
||||||
|
} |
||||||
|
|
||||||
|
//When the tween has finished playing, run the end tasks
|
||||||
|
else { |
||||||
|
//sprite[property] = o.endValue;
|
||||||
|
o.end(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//The `end` method will be called when the tween is finished
|
||||||
|
o.end = () => { |
||||||
|
|
||||||
|
//Set `playing` to `false`
|
||||||
|
o.playing = false; |
||||||
|
|
||||||
|
//Call the tween's `onComplete` method, if it's been
|
||||||
|
//assigned
|
||||||
|
if (o.onComplete) o.onComplete(); |
||||||
|
|
||||||
|
//Remove the tween from the global `tweens` array
|
||||||
|
this.globalTweens.splice(this.globalTweens.indexOf(o), 1); |
||||||
|
|
||||||
|
//If the tween's `yoyo` property is `true`, reverse the array and
|
||||||
|
//use it to create a new tween
|
||||||
|
if (yoyo) { |
||||||
|
this.wait(delayBeforeRepeat).then(() => { |
||||||
|
o.pointsArray = o.pointsArray.reverse(); |
||||||
|
o.start(o.pointsArray); |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Pause and play methods
|
||||||
|
o.pause = () => { |
||||||
|
o.playing = false; |
||||||
|
}; |
||||||
|
o.play = () => { |
||||||
|
o.playing = true; |
||||||
|
}; |
||||||
|
|
||||||
|
//Return the tween object
|
||||||
|
return o; |
||||||
|
} |
||||||
|
|
||||||
|
walkPath( |
||||||
|
sprite, //The sprite
|
||||||
|
originalPathArray, //A 2D array of waypoints
|
||||||
|
totalFrames = 300, //The duration, in frames
|
||||||
|
type = "smoothstep", //The easing type
|
||||||
|
loop = false, //Should the animation loop?
|
||||||
|
yoyo = false, //Shoud the direction reverse?
|
||||||
|
delayBetweenSections = 0 //Delay, in milliseconds, between sections
|
||||||
|
) { |
||||||
|
|
||||||
|
//Clone the path array so that any possible references to sprite
|
||||||
|
//properties are converted into ordinary numbers
|
||||||
|
let pathArray = JSON.parse(JSON.stringify(originalPathArray)); |
||||||
|
|
||||||
|
//Figure out the duration, in frames, of each path section by
|
||||||
|
//dividing the `totalFrames` by the length of the `pathArray`
|
||||||
|
let frames = totalFrames / pathArray.length; |
||||||
|
|
||||||
|
//Set the current point to 0, which will be the first waypoint
|
||||||
|
let currentPoint = 0; |
||||||
|
|
||||||
|
//The `makePath` function creates a single tween between two points and
|
||||||
|
//then schedules the next path to be made after it
|
||||||
|
let makePath = (currentPoint) => { |
||||||
|
|
||||||
|
//Use the `makeTween` function to tween the sprite's
|
||||||
|
//x and y position
|
||||||
|
let tween = this.makeTween([ |
||||||
|
|
||||||
|
//Create the x axis tween between the first x value in the
|
||||||
|
//current point and the x value in the following point
|
||||||
|
[ |
||||||
|
sprite, |
||||||
|
"x", |
||||||
|
pathArray[currentPoint][0], |
||||||
|
pathArray[currentPoint + 1][0], |
||||||
|
frames, |
||||||
|
type |
||||||
|
], |
||||||
|
|
||||||
|
//Create the y axis tween in the same way
|
||||||
|
[ |
||||||
|
sprite, |
||||||
|
"y", |
||||||
|
pathArray[currentPoint][1], |
||||||
|
pathArray[currentPoint + 1][1], |
||||||
|
frames, |
||||||
|
type |
||||||
|
] |
||||||
|
]); |
||||||
|
|
||||||
|
//When the tween is complete, advance the `currentPoint` by one.
|
||||||
|
//Add an optional delay between path segments, and then make the
|
||||||
|
//next connecting path
|
||||||
|
tween.onComplete = () => { |
||||||
|
|
||||||
|
//Advance to the next point
|
||||||
|
currentPoint += 1; |
||||||
|
|
||||||
|
//If the sprite hasn't reached the end of the
|
||||||
|
//path, tween the sprite to the next point
|
||||||
|
if (currentPoint < pathArray.length - 1) { |
||||||
|
this.wait(delayBetweenSections).then(() => { |
||||||
|
tween = makePath(currentPoint); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
//If we've reached the end of the path, optionally
|
||||||
|
//loop and yoyo it
|
||||||
|
else { |
||||||
|
|
||||||
|
//Reverse the path if `loop` is `true`
|
||||||
|
if (loop) { |
||||||
|
|
||||||
|
//Reverse the array if `yoyo` is `true`
|
||||||
|
if (yoyo) pathArray.reverse(); |
||||||
|
|
||||||
|
//Optionally wait before restarting
|
||||||
|
this.wait(delayBetweenSections).then(() => { |
||||||
|
|
||||||
|
//Reset the `currentPoint` to 0 so that we can
|
||||||
|
//restart at the first point
|
||||||
|
currentPoint = 0; |
||||||
|
|
||||||
|
//Set the sprite to the first point
|
||||||
|
sprite.x = pathArray[0][0]; |
||||||
|
sprite.y = pathArray[0][1]; |
||||||
|
|
||||||
|
//Make the first new path
|
||||||
|
tween = makePath(currentPoint); |
||||||
|
|
||||||
|
//... and so it continues!
|
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Return the path tween to the main function
|
||||||
|
return tween; |
||||||
|
}; |
||||||
|
|
||||||
|
//Make the first path using the internal `makePath` function (below)
|
||||||
|
let tween = makePath(currentPoint); |
||||||
|
|
||||||
|
//Pass the tween back to the main program
|
||||||
|
return tween; |
||||||
|
} |
||||||
|
|
||||||
|
walkCurve( |
||||||
|
sprite, //The sprite
|
||||||
|
pathArray, //2D array of Bezier curves
|
||||||
|
totalFrames = 300, //The duration, in frames
|
||||||
|
type = "smoothstep", //The easing type
|
||||||
|
loop = false, //Should the animation loop?
|
||||||
|
yoyo = false, //Should the direction reverse?
|
||||||
|
delayBeforeContinue = 0 //Delay, in milliseconds, between sections
|
||||||
|
) { |
||||||
|
|
||||||
|
//Divide the `totalFrames` into sections for each part of the path
|
||||||
|
let frames = totalFrames / pathArray.length; |
||||||
|
|
||||||
|
//Set the current curve to 0, which will be the first one
|
||||||
|
let currentCurve = 0; |
||||||
|
|
||||||
|
//The `makePath` function
|
||||||
|
let makePath = (currentCurve) => { |
||||||
|
|
||||||
|
//Use the custom `followCurve` function to make
|
||||||
|
//a sprite follow a curve
|
||||||
|
let tween = this.followCurve( |
||||||
|
sprite, |
||||||
|
pathArray[currentCurve], |
||||||
|
frames, |
||||||
|
type |
||||||
|
); |
||||||
|
|
||||||
|
//When the tween is complete, advance the `currentCurve` by one.
|
||||||
|
//Add an optional delay between path segments, and then make the
|
||||||
|
//next path
|
||||||
|
tween.onComplete = () => { |
||||||
|
currentCurve += 1; |
||||||
|
if (currentCurve < pathArray.length) { |
||||||
|
this.wait(delayBeforeContinue).then(() => { |
||||||
|
tween = makePath(currentCurve); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
//If we've reached the end of the path, optionally
|
||||||
|
//loop and reverse it
|
||||||
|
else { |
||||||
|
if (loop) { |
||||||
|
if (yoyo) { |
||||||
|
|
||||||
|
//Reverse order of the curves in the `pathArray`
|
||||||
|
pathArray.reverse(); |
||||||
|
|
||||||
|
//Reverse the order of the points in each curve
|
||||||
|
pathArray.forEach(curveArray => curveArray.reverse()); |
||||||
|
} |
||||||
|
|
||||||
|
//After an optional delay, reset the sprite to the
|
||||||
|
//beginning of the path and make the next new path
|
||||||
|
this.wait(delayBeforeContinue).then(() => { |
||||||
|
currentCurve = 0; |
||||||
|
sprite.x = pathArray[0][0]; |
||||||
|
sprite.y = pathArray[0][1]; |
||||||
|
tween = makePath(currentCurve); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Return the path tween to the main function
|
||||||
|
return tween; |
||||||
|
}; |
||||||
|
|
||||||
|
//Make the first path
|
||||||
|
let tween = makePath(currentCurve); |
||||||
|
|
||||||
|
//Pass the tween back to the main program
|
||||||
|
return tween; |
||||||
|
} |
||||||
|
|
||||||
|
//4. Utilities
|
||||||
|
|
||||||
|
/* |
||||||
|
The `wait` method lets you set up a timed sequence of events |
||||||
|
|
||||||
|
wait(1000) |
||||||
|
.then(() => console.log("One")) |
||||||
|
.then(() => wait(1000)) |
||||||
|
.then(() => console.log("Two")) |
||||||
|
.then(() => wait(1000)) |
||||||
|
.then(() => console.log("Three")) |
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
wait(duration = 0) { |
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
setTimeout(resolve, duration); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
//A utility to remove tweens from the game
|
||||||
|
removeTween(tweenObject) { |
||||||
|
|
||||||
|
//Remove the tween if `tweenObject` doesn't have any nested
|
||||||
|
//tween objects
|
||||||
|
if (!tweenObject.tweens) { |
||||||
|
tweenObject.pause(); |
||||||
|
|
||||||
|
//array.splice(-1,1) will always remove last elemnt of array, so this
|
||||||
|
//extra check prevents that (Thank you, MCumic10! https://github.com/kittykatattack/charm/issues/5)
|
||||||
|
if (this.globalTweens.indexOf(tweenObject) != -1) { |
||||||
|
this.globalTweens.splice(this.globalTweens.indexOf(tweenObject), 1); |
||||||
|
} |
||||||
|
|
||||||
|
//Otherwise, remove the nested tween objects
|
||||||
|
} else { |
||||||
|
tweenObject.pause(); |
||||||
|
tweenObject.tweens.forEach(element => { |
||||||
|
this.globalTweens.splice(this.globalTweens.indexOf(element), 1); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
update() { |
||||||
|
|
||||||
|
//Update all the tween objects in the `globalTweens` array
|
||||||
|
if (this.globalTweens.length > 0) { |
||||||
|
for (let i = this.globalTweens.length - 1; i >= 0; i--) { |
||||||
|
let tween = this.globalTweens[i]; |
||||||
|
if (tween) tween.update(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
/** |
||||||
|
* 属性 |
||||||
|
*/ |
||||||
|
export class PropertyInfo { |
||||||
|
constructor(instanceData: any) { |
||||||
|
this.Tag = instanceData.tag; |
||||||
|
this.Order = instanceData.order; |
||||||
|
this.Enabled = instanceData.enabled; |
||||||
|
this.Visible = instanceData.visible; |
||||||
|
this.Required = instanceData.required; |
||||||
|
this.RuleName = instanceData.ruleName; |
||||||
|
this.RuleValue = instanceData.ruleValue; |
||||||
|
this.PhysicalUnit = instanceData.physicalUnit; |
||||||
|
this.PropertyName = instanceData.propertyName; |
||||||
|
this.PropertyType = instanceData.propertyType; |
||||||
|
this.PropertyValue = instanceData.propertyValue; |
||||||
|
} |
||||||
|
/** |
||||||
|
* 标记位,用于扩展 |
||||||
|
*/ |
||||||
|
public Tag: string; |
||||||
|
/** |
||||||
|
* 属性排序 |
||||||
|
*/ |
||||||
|
public Order: number; |
||||||
|
/** |
||||||
|
* 是否启用 |
||||||
|
*/ |
||||||
|
public Enabled: boolean; |
||||||
|
/** |
||||||
|
* 是否可见 |
||||||
|
*/ |
||||||
|
public Visible: boolean; |
||||||
|
/** |
||||||
|
* 必填 |
||||||
|
*/ |
||||||
|
public Required: boolean; |
||||||
|
/** |
||||||
|
* 验证规则名称 |
||||||
|
*/ |
||||||
|
public RuleName: string; |
||||||
|
/** |
||||||
|
* 验证规则值 |
||||||
|
*/ |
||||||
|
public RuleValue: string; |
||||||
|
/** |
||||||
|
* 物理单位 |
||||||
|
*/ |
||||||
|
public PhysicalUnit: string; |
||||||
|
/** |
||||||
|
* 属性名称 |
||||||
|
*/ |
||||||
|
public PropertyName: string; |
||||||
|
/** |
||||||
|
* 属性类型 |
||||||
|
*/ |
||||||
|
public PropertyType: number; |
||||||
|
/** |
||||||
|
* 属性值 |
||||||
|
*/ |
||||||
|
public PropertyValue: string; |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 箭头 |
||||||
|
* 创建一个只有2个点组成的箭头 |
||||||
|
*/ |
||||||
|
export class Arrows extends PIXI.Container { |
||||||
|
public line: PIXI.Graphics = new PIXI.Graphics(); |
||||||
|
public ready = false; |
||||||
|
constructor(public assetData: any, private workingArea: WorkingAreaComponent) { |
||||||
|
super(); |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
this.name = this.assetData.Id; |
||||||
|
this.addChild(this.line); |
||||||
|
this.refresh(); |
||||||
|
this.interactive = true; |
||||||
|
this.on('mousedown', event => { |
||||||
|
if (!this.ready) { return; } |
||||||
|
event.stopPropagation(); |
||||||
|
this.workingArea.selection.selectOne(this); |
||||||
|
}); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 刷新 |
||||||
|
*/ |
||||||
|
public refresh() { |
||||||
|
this.line.clear(); |
||||||
|
this.line.lineStyle(5, 0xff0000, 1); |
||||||
|
this.line.moveTo(this.assetData.pointA.x, this.assetData.pointA.y); |
||||||
|
this.line.lineTo(this.assetData.pointB.x, this.assetData.pointB.y); |
||||||
|
|
||||||
|
const angle = Math.atan2((this.assetData.pointB.y - this.assetData.pointA.y), (this.assetData.pointB.x - this.assetData.pointA.x)) |
||||||
|
* (180 / Math.PI) + 90; |
||||||
|
|
||||||
|
this.line.beginFill(0xff0000); |
||||||
|
console.log(Math.PI / 180 / 1.6); |
||||||
|
this.line.drawStar(this.assetData.pointB.x, this.assetData.pointB.y, 3, 10, 0, (Math.PI / 180 * angle)); |
||||||
|
this.line.endFill(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,322 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
import { AxShape } from './axShape'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 墙面 |
||||||
|
*/ |
||||||
|
export class AxArrowConnector extends AxShape { |
||||||
|
|
||||||
|
line: PIXI.Graphics; |
||||||
|
text: PIXI.Text; |
||||||
|
style = new PIXI.TextStyle({ |
||||||
|
fontFamily: 'Arial', |
||||||
|
fontSize: 18, |
||||||
|
fontStyle: 'normal', |
||||||
|
fontWeight: 'bold', |
||||||
|
fill: ['#000000'], |
||||||
|
stroke: '#ffffff', |
||||||
|
strokeThickness: 3, |
||||||
|
dropShadow: true, |
||||||
|
dropShadowColor: '#000000', |
||||||
|
dropShadowBlur: 3, |
||||||
|
dropShadowAngle: Math.PI / 6, |
||||||
|
dropShadowDistance: 1, |
||||||
|
wordWrap: false, |
||||||
|
wordWrapWidth: 100, |
||||||
|
}); |
||||||
|
pts: PIXI.Point[]; |
||||||
|
|
||||||
|
constructor(assetData: any, workingArea: WorkingAreaComponent) { |
||||||
|
super(assetData, workingArea); |
||||||
|
this.text = new PIXI.Text(this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos?.find((item: { PropertyName: string; }) => |
||||||
|
item.PropertyName === '名称/编号')?.PropertyValue, this.style); |
||||||
|
this.line = new PIXI.Graphics(); |
||||||
|
this.addChild(this.text); |
||||||
|
this.addChild(this.line); |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
this.refresh(this.line, this.assetData.MultiPoint); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新形状 |
||||||
|
*/ |
||||||
|
public refresh(c: PIXI.Graphics, pts: PIXI.Point[]): void { |
||||||
|
if (pts.length < 2) { |
||||||
|
this.text.position = pts[0]; |
||||||
|
return; |
||||||
|
} |
||||||
|
const strokeWidth = 1; |
||||||
|
const startWidth = 30 + strokeWidth; |
||||||
|
const endWidth = 30 + strokeWidth; |
||||||
|
const edgeWidth = 10; |
||||||
|
const openEnded = false; |
||||||
|
const markerStart = false;// 起始箭头
|
||||||
|
const markerEnd = false;// 结束箭头
|
||||||
|
const spacing = (openEnded) ? 0 : 0 + strokeWidth / 2; |
||||||
|
const startSize = 30 + strokeWidth; |
||||||
|
const endSize = 30 + strokeWidth; |
||||||
|
const isRounded = true; |
||||||
|
|
||||||
|
const pe = pts[pts.length - 1]; |
||||||
|
|
||||||
|
let i0 = 1; |
||||||
|
|
||||||
|
while (i0 < pts.length - 1 && pts[i0].x === pts[0].x && pts[i0].y === pts[0].y) { |
||||||
|
i0++; |
||||||
|
} |
||||||
|
|
||||||
|
const dx = pts[i0].x - pts[0].x; |
||||||
|
const dy = pts[i0].y - pts[0].y; |
||||||
|
const dist = Math.sqrt(dx * dx + dy * dy); |
||||||
|
|
||||||
|
if (dist === 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
let nx = dx / dist; |
||||||
|
let nx1 = nx; |
||||||
|
let nx2 = nx; |
||||||
|
let ny = dy / dist; |
||||||
|
let ny2 = ny; |
||||||
|
let ny1 = ny; |
||||||
|
let orthx = edgeWidth * ny; |
||||||
|
let orthy = -edgeWidth * nx; |
||||||
|
|
||||||
|
const fns = []; |
||||||
|
|
||||||
|
// if (isRounded) {
|
||||||
|
// // c.setLineJoin('round');
|
||||||
|
// c.lineTextureStyle({ join: PIXI.LINE_JOIN.ROUND });
|
||||||
|
// } else if (pts.length > 2) {
|
||||||
|
// // Only mitre if there are waypoints
|
||||||
|
// // c.setMiterLimit(1.42);
|
||||||
|
// c.lineTextureStyle({ miterLimit: 1.42 });
|
||||||
|
// }
|
||||||
|
// c.lineStyle(1, 0x000000, 1);
|
||||||
|
c.clear(); |
||||||
|
c.lineTextureStyle({ width: 1, color: 0x00000, join: PIXI.LINE_JOIN.ROUND }); |
||||||
|
c.beginFill(0xffffff); |
||||||
|
const startNx = nx; |
||||||
|
const startNy = ny; |
||||||
|
|
||||||
|
if (markerStart && !openEnded) { |
||||||
|
this.paintMarker(c, pts[0].x, pts[0].y, nx, ny, startSize, startWidth, edgeWidth, spacing, true); |
||||||
|
} else { |
||||||
|
const outStartX = pts[0].x + orthx / 2 + spacing * nx; |
||||||
|
const outStartY = pts[0].y + orthy / 2 + spacing * ny; |
||||||
|
const inEndX = pts[0].x - orthx / 2 + spacing * nx; |
||||||
|
const inEndY = pts[0].y - orthy / 2 + spacing * ny; |
||||||
|
|
||||||
|
if (openEnded) { |
||||||
|
c.moveTo(outStartX, outStartY); |
||||||
|
fns.push( () => { |
||||||
|
c.lineTo(inEndX, inEndY); |
||||||
|
}); |
||||||
|
} else { |
||||||
|
c.moveTo(inEndX, inEndY); |
||||||
|
c.lineTo(outStartX, outStartY); |
||||||
|
} |
||||||
|
} |
||||||
|
let dx1 = 0; |
||||||
|
let dy1 = 0; |
||||||
|
let dist1 = 0; |
||||||
|
|
||||||
|
for (let i = 0; i < pts.length - 2; i++) { |
||||||
|
const pos = this.relativeCcw(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, pts[i + 2].x, pts[i + 2].y); |
||||||
|
|
||||||
|
dx1 = pts[i + 2].x - pts[i + 1].x; |
||||||
|
dy1 = pts[i + 2].y - pts[i + 1].y; |
||||||
|
|
||||||
|
dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); |
||||||
|
|
||||||
|
if (dist1 !== 0) { |
||||||
|
nx1 = dx1 / dist1; |
||||||
|
ny1 = dy1 / dist1; |
||||||
|
|
||||||
|
const tmp1 = nx * nx1 + ny * ny1; |
||||||
|
const tmp = Math.max(Math.sqrt((tmp1 + 1) / 2), 0.04); |
||||||
|
|
||||||
|
nx2 = (nx + nx1); |
||||||
|
ny2 = (ny + ny1); |
||||||
|
|
||||||
|
const dist2 = Math.sqrt(nx2 * nx2 + ny2 * ny2); |
||||||
|
|
||||||
|
if (dist2 !== 0) { |
||||||
|
nx2 = nx2 / dist2; |
||||||
|
ny2 = ny2 / dist2; |
||||||
|
|
||||||
|
const strokeWidthFactor = Math.max(tmp, Math.min(1 / 200 + 0.04, 0.35)); |
||||||
|
const angleFactor = (pos !== 0 && isRounded) ? Math.max(0.1, strokeWidthFactor) : Math.max(tmp, 0.06); |
||||||
|
|
||||||
|
const outX = pts[i + 1].x + ny2 * edgeWidth / 2 / angleFactor; |
||||||
|
const outY = pts[i + 1].y - nx2 * edgeWidth / 2 / angleFactor; |
||||||
|
const inX = pts[i + 1].x - ny2 * edgeWidth / 2 / angleFactor; |
||||||
|
const inY = pts[i + 1].y + nx2 * edgeWidth / 2 / angleFactor; |
||||||
|
|
||||||
|
if (pos === 0 || !isRounded) { |
||||||
|
c.lineTo(outX, outY); |
||||||
|
|
||||||
|
((x, y) => { |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(x, y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} else if (pos === -1) { |
||||||
|
const c1x = inX + ny * edgeWidth; |
||||||
|
const c1y = inY - nx * edgeWidth; |
||||||
|
const c2x = inX + ny1 * edgeWidth; |
||||||
|
const c2y = inY - nx1 * edgeWidth; |
||||||
|
c.lineTo(c1x, c1y); |
||||||
|
if (isRounded) { |
||||||
|
c.quadraticCurveTo(outX, outY, c2x, c2y); // 圆角
|
||||||
|
} else { |
||||||
|
c.lineTo(outX, outY); |
||||||
|
} |
||||||
|
((x, y) => { |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(x, y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} else { |
||||||
|
c.lineTo(outX, outY); |
||||||
|
|
||||||
|
((x, y) => { |
||||||
|
const c1x = outX - ny * edgeWidth; |
||||||
|
const c1y = outY + nx * edgeWidth; |
||||||
|
const c2x = outX - ny1 * edgeWidth; |
||||||
|
const c2y = outY + nx1 * edgeWidth; |
||||||
|
|
||||||
|
fns.push(() => { |
||||||
|
if (isRounded) { |
||||||
|
c.quadraticCurveTo(x, y, c1x, c1y); |
||||||
|
} else { |
||||||
|
c.lineTo(x, y); |
||||||
|
} |
||||||
|
}); |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(c2x, c2y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} |
||||||
|
|
||||||
|
nx = nx1; |
||||||
|
ny = ny1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
orthx = edgeWidth * ny1; |
||||||
|
orthy = - edgeWidth * nx1; |
||||||
|
|
||||||
|
if (markerEnd && !openEnded) { |
||||||
|
this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, false); |
||||||
|
} else { |
||||||
|
c.lineTo(pe.x - spacing * nx1 + orthx / 2, pe.y - spacing * ny1 + orthy / 2); |
||||||
|
|
||||||
|
const inStartX = pe.x - spacing * nx1 - orthx / 2; |
||||||
|
const inStartY = pe.y - spacing * ny1 - orthy / 2; |
||||||
|
|
||||||
|
if (!openEnded) { |
||||||
|
c.lineTo(inStartX, inStartY); |
||||||
|
} else { |
||||||
|
c.moveTo(inStartX, inStartY); |
||||||
|
|
||||||
|
fns.splice(0, 0, () => { |
||||||
|
c.moveTo(inStartX, inStartY); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (let i = fns.length - 1; i >= 0; i--) { |
||||||
|
fns[i](); |
||||||
|
} |
||||||
|
c.closePath(); |
||||||
|
c.endFill(); |
||||||
|
// if (openEnded)
|
||||||
|
// {
|
||||||
|
// c.end();
|
||||||
|
// c.stroke();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// c.close();
|
||||||
|
// c.fillAndStroke();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// c.setShadow(false);
|
||||||
|
|
||||||
|
// c.setMiterLimit(4);
|
||||||
|
|
||||||
|
// if (isRounded)
|
||||||
|
// {
|
||||||
|
// c.setLineJoin('flat');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (pts.length > 2)
|
||||||
|
// {
|
||||||
|
// c.setMiterLimit(4);
|
||||||
|
// if (markerStart && !openEnded)
|
||||||
|
// {
|
||||||
|
// c.begin();
|
||||||
|
// this.paintMarker(c, pts[0].x, pts[0].y, startNx, startNy, startSize, startWidth, edgeWidth, spacing, true);
|
||||||
|
// c.stroke();
|
||||||
|
// c.end();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (markerEnd && !openEnded)
|
||||||
|
// {
|
||||||
|
// c.begin();
|
||||||
|
// this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, true);
|
||||||
|
// c.stroke();
|
||||||
|
// c.end();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} |
||||||
|
paintMarker(c: PIXI.Graphics, ptX: number, ptY: number, nx: number, ny: number, |
||||||
|
size: number, arrowWidth: number, edgeWidth: number, spacing: number, initialMove: boolean) { |
||||||
|
const widthArrowRatio = edgeWidth / arrowWidth; |
||||||
|
const orthx = edgeWidth * ny / 2; |
||||||
|
const orthy = -edgeWidth * nx / 2; |
||||||
|
|
||||||
|
const spaceX = (spacing + size) * nx; |
||||||
|
const spaceY = (spacing + size) * ny; |
||||||
|
|
||||||
|
if (initialMove) { |
||||||
|
c.moveTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
||||||
|
} else { |
||||||
|
c.lineTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
||||||
|
} |
||||||
|
c.lineTo(ptX - orthx / widthArrowRatio + spaceX, ptY - orthy / widthArrowRatio + spaceY); |
||||||
|
c.lineTo(ptX + spacing * nx, ptY + spacing * ny); |
||||||
|
c.lineTo(ptX + orthx / widthArrowRatio + spaceX, ptY + orthy / widthArrowRatio + spaceY); |
||||||
|
c.lineTo(ptX + orthx + spaceX, ptY + orthy + spaceY); |
||||||
|
} |
||||||
|
relativeCcw(x1: number, y1: number, x2: number, y2: number, px: number, py: number) { |
||||||
|
x2 -= x1; |
||||||
|
y2 -= y1; |
||||||
|
px -= x1; |
||||||
|
py -= y1; |
||||||
|
let ccw = px * y2 - py * x2; |
||||||
|
|
||||||
|
if (ccw === 0.0) { |
||||||
|
ccw = px * x2 + py * y2; |
||||||
|
|
||||||
|
if (ccw > 0.0) { |
||||||
|
px -= x2; |
||||||
|
py -= y2; |
||||||
|
ccw = px * x2 + py * y2; |
||||||
|
|
||||||
|
if (ccw < 0.0) { |
||||||
|
ccw = 0.0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); |
||||||
|
} |
||||||
|
|
||||||
|
redraw(): void{ |
||||||
|
this.refresh(this.line, this.assetData.MultiPoint); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,443 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import * as ObjectID from 'bson-objectid'; |
||||||
|
import { GameMode } from './gameMode'; |
||||||
|
import { Pipeline } from './pipeline'; |
||||||
|
import { PaintMode } from './paintModel'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
import { PropertyInfo } from './PropertyInfo'; |
||||||
|
import { AxShape } from './axShape'; |
||||||
|
import { Sprite } from 'pixi.js'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 安信图片形状 |
||||||
|
* AxImageShape |
||||||
|
*/ |
||||||
|
export class AxImageShape extends AxShape { |
||||||
|
style = new PIXI.TextStyle({ |
||||||
|
fontFamily: 'Arial', |
||||||
|
fontSize: 18, |
||||||
|
fontStyle: 'normal', |
||||||
|
fontWeight: 'bold', |
||||||
|
fill: ['#000000'], |
||||||
|
stroke: '#ffffff', |
||||||
|
strokeThickness: 3, |
||||||
|
dropShadow: true, |
||||||
|
dropShadowColor: '#000000', |
||||||
|
dropShadowBlur: 3, |
||||||
|
dropShadowAngle: Math.PI / 6, |
||||||
|
dropShadowDistance: 1, |
||||||
|
wordWrap: false, |
||||||
|
wordWrapWidth: 100, |
||||||
|
}); |
||||||
|
|
||||||
|
text = new PIXI.Text(this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style); |
||||||
|
|
||||||
|
/** |
||||||
|
* 选中圆点 |
||||||
|
*/ |
||||||
|
|
||||||
|
image: PIXI.Sprite; |
||||||
|
selectionBox = new PIXI.Graphics(); |
||||||
|
connectPointTexture = PIXI.Texture.from('assets/images/handle-secondary.png'); |
||||||
|
connectPoint: Sprite; |
||||||
|
// 可移动的
|
||||||
|
|
||||||
|
// 可选中的
|
||||||
|
|
||||||
|
// up: PIXI.Sprite;
|
||||||
|
// down: PIXI.Sprite;
|
||||||
|
// left: PIXI.Sprite;
|
||||||
|
// right: PIXI.Sprite;
|
||||||
|
// upLeft: PIXI.Sprite;
|
||||||
|
// upRight: PIXI.Sprite;
|
||||||
|
// downLeft: PIXI.Sprite;
|
||||||
|
// downRight: PIXI.Sprite;
|
||||||
|
constructor(assetData: any, workingArea: WorkingAreaComponent) { |
||||||
|
super(assetData, workingArea); |
||||||
|
this.x = this.assetData.Point.x; |
||||||
|
this.y = this.assetData.Point.y; |
||||||
|
this.name = this.assetData.Id; |
||||||
|
this.image = PIXI.Sprite.from(this.assetData.ImageUrl); |
||||||
|
this.image.angle = this.assetData.Angle; |
||||||
|
|
||||||
|
this.image.x = 0; |
||||||
|
this.image.y = 0; |
||||||
|
this.image.width = this.assetData.Width; |
||||||
|
this.image.height = this.assetData.Height; |
||||||
|
this.image.alpha = 1; |
||||||
|
this.image.anchor.set(0.5); |
||||||
|
// this.image.interactive = true;
|
||||||
|
// this.image.buttonMode = true;
|
||||||
|
// this.image
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// this.workingArea.selection.selectOne(this);
|
||||||
|
// // this.paintingPipeline(this.x, this.y);
|
||||||
|
// // 如果链接对象不为空,禁止移动
|
||||||
|
// if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
|
||||||
|
// event.currentTarget.parent.data = event.data;
|
||||||
|
// event.currentTarget.parent.alpha = 0.5;
|
||||||
|
// event.currentTarget.parent.dragging = true;
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on('mouseup', event => {
|
||||||
|
// if (event.currentTarget.parent.dragging) {
|
||||||
|
// event.currentTarget.parent.alpha = 1;
|
||||||
|
// event.currentTarget.parent.dragging = false;
|
||||||
|
// event.currentTarget.parent.data = null;
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on('mouseupoutside', event => {
|
||||||
|
// if (event.currentTarget.parent.dragging) {
|
||||||
|
// event.currentTarget.parent.alpha = 1;
|
||||||
|
// event.currentTarget.parent.dragging = false;
|
||||||
|
// event.currentTarget.parent.data = null;
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on('mousemove', event => {
|
||||||
|
// if (event.currentTarget.parent.dragging) {
|
||||||
|
// // // 如果拖动过程中发现父对象不是背景图
|
||||||
|
// // if (this.parent !== this.workingArea.backgroundImage) {
|
||||||
|
// // this.setParent(this.workingArea.backgroundImage);
|
||||||
|
// // if (this.assetData.FixedSize) {
|
||||||
|
// // const scale = 1 / this.workingArea.backgroundImage.scale.x;
|
||||||
|
// // this.scale.set(scale);
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent);
|
||||||
|
// event.currentTarget.parent.x = newPosition.x;
|
||||||
|
// event.currentTarget.parent.y = newPosition.y;
|
||||||
|
// this.assetData.Point = new PIXI.Point(this.x, this.y);
|
||||||
|
// this.workingArea.canvasData.isChange = true;
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on('rightclick', event => {
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// if (this.workingArea.previewImage !== null
|
||||||
|
// && this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
|
||||||
|
// this.workingArea.previewImage.visible = false;
|
||||||
|
// }
|
||||||
|
// // if (this.assetData.CanConnect) {
|
||||||
|
// // this.setSelectionBox(true, this.image);
|
||||||
|
// // }
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// if (this.workingArea.previewImage !== null
|
||||||
|
// && this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
|
||||||
|
// this.workingArea.previewImage.visible = true;
|
||||||
|
// }
|
||||||
|
// // if (this.assetData.CanConnect) {
|
||||||
|
// // this.setSelectionBox(false);
|
||||||
|
// // }
|
||||||
|
// });
|
||||||
|
this.text.x = this.image.x; |
||||||
|
this.text.y = this.image.y - this.image.height / 2; |
||||||
|
this.text.anchor.set(0.5, 1); |
||||||
|
|
||||||
|
if (this.assetData.GameMode === 2) { |
||||||
|
this.text.visible = false; |
||||||
|
} |
||||||
|
this.addChild(this.text); |
||||||
|
this.addChild(this.image); |
||||||
|
this.addChild(this.selectionBox); |
||||||
|
|
||||||
|
if (this.assetData.CanConnect) { |
||||||
|
// connectPoint
|
||||||
|
this.connectPoint = new PIXI.Sprite(this.connectPointTexture); |
||||||
|
this.connectPoint.anchor.set(0.5); |
||||||
|
this.connectPoint.x = this.image.x; |
||||||
|
this.connectPoint.y = this.image.y; |
||||||
|
this.addChild(this.connectPoint); |
||||||
|
this.connectPoint.interactive = true; |
||||||
|
this.connectPoint |
||||||
|
.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
this.paintingPipeline(this.x, this.y); |
||||||
|
}) |
||||||
|
.on('mouseover', event => { |
||||||
|
this.setSelectionBox(true, this.connectPoint); |
||||||
|
}) |
||||||
|
.on('mouseout', event => { |
||||||
|
this.setSelectionBox(false); |
||||||
|
}); |
||||||
|
// // up
|
||||||
|
// this.up = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.up.anchor.set(0.5);
|
||||||
|
// this.up.x = this.image.x;
|
||||||
|
// this.up.y = this.image.y - (this.image.height / 2);
|
||||||
|
// this.addChild(this.up);
|
||||||
|
// this.up.interactive = true;
|
||||||
|
// this.up
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.up.x, this.up.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.up);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // down
|
||||||
|
// this.down = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.down.anchor.set(0.5);
|
||||||
|
// this.down.x = this.image.x;
|
||||||
|
// this.down.y = this.image.y + (this.image.height / 2);
|
||||||
|
// this.addChild(this.down);
|
||||||
|
// this.down.interactive = true;
|
||||||
|
// this.down
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.down.x, this.down.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.down);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // left
|
||||||
|
// this.left = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.left.anchor.set(0.5);
|
||||||
|
// this.left.x = this.image.x - (this.image.width / 2);
|
||||||
|
// this.left.y = this.image.y;
|
||||||
|
// this.addChild(this.left);
|
||||||
|
// this.left.interactive = true;
|
||||||
|
// this.left
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.left.x, this.left.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.left);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // right
|
||||||
|
// this.right = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.right.anchor.set(0.5);
|
||||||
|
// this.right.x = this.image.x + (this.image.width / 2);
|
||||||
|
// this.right.y = this.image.y;
|
||||||
|
// this.addChild(this.right);
|
||||||
|
// this.right.interactive = true;
|
||||||
|
// this.right
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.right.x, this.right.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.right);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // up-left
|
||||||
|
// this.upLeft = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.upLeft.anchor.set(0.5);
|
||||||
|
// this.upLeft.x = this.image.x - (this.image.width / 2);
|
||||||
|
// this.upLeft.y = this.image.y - (this.image.height / 2);
|
||||||
|
// this.addChild(this.upLeft);
|
||||||
|
// this.upLeft.interactive = true;
|
||||||
|
// this.upLeft
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.upLeft.x, this.upLeft.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.upLeft);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // up-right
|
||||||
|
// this.upRight = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.upRight.anchor.set(0.5);
|
||||||
|
// this.upRight.x = this.image.x + (this.image.width / 2);
|
||||||
|
// this.upRight.y = this.image.y - (this.image.height / 2);
|
||||||
|
// this.addChild(this.upRight);
|
||||||
|
// this.upRight.interactive = true;
|
||||||
|
// this.upRight
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.upRight.x, this.upRight.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.upRight);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // down-left
|
||||||
|
// this.downLeft = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.downLeft.anchor.set(0.5);
|
||||||
|
// this.downLeft.x = this.image.x - (this.image.width / 2);
|
||||||
|
// this.downLeft.y = this.image.y + (this.image.height / 2);
|
||||||
|
// this.addChild(this.downLeft);
|
||||||
|
// this.downLeft.interactive = true;
|
||||||
|
// this.downLeft
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.downLeft.x, this.downLeft.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.downLeft);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
// // down-right
|
||||||
|
// this.downRight = new PIXI.Sprite(this.selectedPointTexture);
|
||||||
|
// this.downRight.anchor.set(0.5);
|
||||||
|
// this.downRight.x = this.image.x + (this.image.width / 2);
|
||||||
|
// this.downRight.y = this.image.y + (this.image.height / 2);
|
||||||
|
// this.addChild(this.downRight);
|
||||||
|
// this.downRight.interactive = true;
|
||||||
|
// this.downRight
|
||||||
|
// .on('mousedown', event => {
|
||||||
|
// event.stopPropagation();
|
||||||
|
// const pt = this.toGlobal(new PIXI.Point(this.downRight.x, this.downRight.y));
|
||||||
|
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
|
||||||
|
// this.paintingPipeline(pt2.x, pt2.y);
|
||||||
|
// })
|
||||||
|
// .on('mouseover', event => {
|
||||||
|
// this.setSelectionBox(true, this.downRight);
|
||||||
|
// })
|
||||||
|
// .on('mouseout', event => {
|
||||||
|
// this.setSelectionBox(false);
|
||||||
|
// });
|
||||||
|
|
||||||
|
this.showConnectionPoint(false); |
||||||
|
} |
||||||
|
} |
||||||
|
// 设置选择框
|
||||||
|
public setSelectionBox(b: boolean, sprite?: PIXI.Sprite) { |
||||||
|
if (b) { |
||||||
|
this.selectionBox.lineStyle(2, 0x00EB00, 1); |
||||||
|
this.selectionBox.position = sprite.position; |
||||||
|
this.selectionBox.drawRect(- sprite.width / 2, - sprite.height / 2, sprite.width, sprite.height); |
||||||
|
// const p0 = new PIXI.Point(- sprite.width / 2, - sprite.height / 2);
|
||||||
|
// const pe = new PIXI.Point(sprite.width / 2, sprite.height / 2);
|
||||||
|
// const pw = new PIXI.Point(p0.x + sprite.width, p0.y);
|
||||||
|
// const ph = new PIXI.Point(p0.x, p0.y + sprite.height);
|
||||||
|
// this.drawDashedLine(this.selectionBox, p0, pw, 0x1234ff);
|
||||||
|
// this.drawDashedLine(this.selectionBox, p0, ph, 0x1234ff);
|
||||||
|
// this.drawDashedLine(this.selectionBox, pe, pw, 0x1234ff);
|
||||||
|
// this.drawDashedLine(this.selectionBox, pe, ph, 0x1234ff);
|
||||||
|
} else { |
||||||
|
this.selectionBox.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
// 设置名称
|
||||||
|
public setNameVisible(value: boolean, mode: GameMode) { |
||||||
|
if (this.assetData.GameMode === mode) { |
||||||
|
this.text.visible = value; |
||||||
|
} |
||||||
|
} |
||||||
|
// 显示连接点
|
||||||
|
public showConnectionPoint(b: boolean) { |
||||||
|
this.connectPoint.visible = b; |
||||||
|
// this.up.visible = b;
|
||||||
|
// this.down.visible = b;
|
||||||
|
// this.left.visible = b;
|
||||||
|
// this.right.visible = b;
|
||||||
|
// this.upLeft.visible = b;
|
||||||
|
// this.downLeft.visible = b;
|
||||||
|
// this.upRight.visible = b;
|
||||||
|
// this.downRight.visible = b;
|
||||||
|
} |
||||||
|
paintingPipeline(x: number, y: number) { |
||||||
|
if (this.assetData.CanConnect) { |
||||||
|
if (this.workingArea.getPaintMode() === PaintMode.Pipeline) { |
||||||
|
if (this.workingArea.paintingPipeline === null) { |
||||||
|
this.workingArea.previewLineSegment.visible = true; |
||||||
|
this.workingArea.currentClickPoint.position = |
||||||
|
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y); |
||||||
|
this.workingArea.paintPoints.push(new PIXI.Point(x, y)); |
||||||
|
const json = JSON.parse(JSON.stringify(this.workingArea.canvasData.selectTemplateData.propertyInfos)); |
||||||
|
const list = []; |
||||||
|
json.forEach(element => { |
||||||
|
const property = new PropertyInfo(element); |
||||||
|
list.push(property); |
||||||
|
}); |
||||||
|
const tempData = { |
||||||
|
TemplateId: this.workingArea.canvasData.selectTemplateData.id, |
||||||
|
CanConnect: this.workingArea.canvasData.selectTemplateData.canConnect, |
||||||
|
Pipelines: new Array(), |
||||||
|
FloorId: this.workingArea.canvasData.selectStorey.id, |
||||||
|
Angle: this.workingArea.canvasData.selectTemplateData.angle, |
||||||
|
Color: this.workingArea.canvasData.selectTemplateData.color, |
||||||
|
Enabled: this.workingArea.canvasData.selectTemplateData.enabled, |
||||||
|
FillMode: this.workingArea.canvasData.selectTemplateData.fillMode, |
||||||
|
FireElementId: this.workingArea.canvasData.selectTemplateData.fireElementId, |
||||||
|
FixedSize: this.workingArea.canvasData.selectTemplateData.fixedSize, |
||||||
|
Height : 32, |
||||||
|
Width : 32, |
||||||
|
Id: ObjectID.default.generate(), |
||||||
|
ImageUrl: this.workingArea.canvasData.selectTemplateData.imageUrl, |
||||||
|
InteractiveMode: this.workingArea.canvasData.selectTemplateData.interactiveMode, |
||||||
|
MultiPoint : JSON.parse(JSON.stringify(this.workingArea.paintPoints)), |
||||||
|
Point: new PIXI.Point(0, 0), |
||||||
|
Name : this.workingArea.canvasData.selectTemplateData.name, |
||||||
|
PropertyInfos: list, |
||||||
|
Border : this.workingArea.canvasData.selectTemplateData.border, |
||||||
|
DrawMode : this.workingArea.canvasData.selectTemplateData.drawMode, |
||||||
|
Thickness : this.workingArea.canvasData.selectTemplateData.thickness, |
||||||
|
IsFromBuilding : this.workingArea.canvasData.selectTemplateData.isFromBuilding, |
||||||
|
GameMode: this.workingArea.canvasData.gameMode, |
||||||
|
LinkedObjects: new Array(this.assetData.Id), |
||||||
|
}; |
||||||
|
this.workingArea.paintingPipeline = new Pipeline(tempData, this.workingArea); |
||||||
|
this.assetData.Pipelines.push(this.workingArea.paintingPipeline.assetData.Id); |
||||||
|
this.workingArea.emit('createIcon', this.workingArea.paintingPipeline); |
||||||
|
} else { |
||||||
|
this.workingArea.previewLineSegment.visible = false; |
||||||
|
this.workingArea.currentClickPoint.position = |
||||||
|
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y); |
||||||
|
this.workingArea.paintPoints.push(new PIXI.Point(x, y)); |
||||||
|
this.workingArea.paintingPipeline.assetData.MultiPoint = |
||||||
|
JSON.parse(JSON.stringify(this.workingArea.paintPoints)); |
||||||
|
this.workingArea.paintingPipeline.assetData.LinkedObjects.push(this.assetData.Id); |
||||||
|
this.assetData.Pipelines.push(this.workingArea.paintingPipeline.assetData.Id); |
||||||
|
this.workingArea.paintingPipeline.refresh(); |
||||||
|
this.workingArea.initPipelineData(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// 刷新
|
||||||
|
public refresh() { |
||||||
|
if (this.assetData.CanConnect) { |
||||||
|
|
||||||
|
} |
||||||
|
this.image.width = this.assetData.Width; |
||||||
|
this.image.height = this.assetData.Height; |
||||||
|
this.image.angle = this.assetData.Angle; |
||||||
|
this.text.text = this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue; |
||||||
|
this.text.x = this.image.x; |
||||||
|
this.text.y = this.image.y - this.image.height / 2; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
import { Sprite, Texture } from 'pixi.js'; |
||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import { AxShape } from './axShape'; |
||||||
|
|
||||||
|
export class AxPreviewImageShape extends AxShape { |
||||||
|
image: Sprite = null; |
||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
constructor(workingArea: WorkingAreaComponent) { |
||||||
|
super(null, workingArea); |
||||||
|
this.image = new Sprite(); |
||||||
|
this.image.width = 32; |
||||||
|
this.image.height = 32; |
||||||
|
this.image.anchor.set(0.5); |
||||||
|
this.interactive = false; |
||||||
|
this.scale.set(1 / this.workingArea.backgroundImage.scale.x); |
||||||
|
this.addChild(this.image); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 重新设置图片地址 |
||||||
|
* @param url 图片路径 |
||||||
|
*/ |
||||||
|
setImageUrl(url: string) { |
||||||
|
this.image.texture = Texture.from(url); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
import { Constructor } from '@angular/material/core/common-behaviors/constructor'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
import { Point, Rectangle, Graphics, Container } from 'pixi.js'; |
||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 安信形状 |
||||||
|
*/ |
||||||
|
export class AxShape extends Container { |
||||||
|
assetData: any; |
||||||
|
workingArea: WorkingAreaComponent; |
||||||
|
// 可以被移动的
|
||||||
|
moveable = true; |
||||||
|
// 可以被选中的
|
||||||
|
selectable = true; |
||||||
|
|
||||||
|
constructor(assetData: any, workingArea: WorkingAreaComponent) { |
||||||
|
super(); |
||||||
|
this.assetData = assetData; |
||||||
|
this.workingArea = workingArea; |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
this.interactive = true; |
||||||
|
this.buttonMode = true; |
||||||
|
this.on('mousedown', event => { |
||||||
|
console.log(this.assetData); |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.selectable) { |
||||||
|
this.workingArea.selection.selectOne(this); |
||||||
|
} |
||||||
|
if (this.moveable) { |
||||||
|
event.currentTarget.data = event.data; |
||||||
|
event.currentTarget.alpha = 0.5; |
||||||
|
event.currentTarget.dragging = true; |
||||||
|
|
||||||
|
event.currentTarget.dragPoint = event.data.getLocalPosition(event.currentTarget.parent); |
||||||
|
event.currentTarget.dragPoint.x -= event.currentTarget.x; |
||||||
|
event.currentTarget.dragPoint.y -= event.currentTarget.y; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseup', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseupoutside', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mousemove', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent); |
||||||
|
event.currentTarget.x = newPosition.x - event.currentTarget.dragPoint.x; |
||||||
|
event.currentTarget.y = newPosition.y - event.currentTarget.dragPoint.y; |
||||||
|
this.assetData.Point = new PIXI.Point(this.x, this.y); |
||||||
|
this.workingArea.canvasData.isChange = true; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('rightclick', event => { |
||||||
|
|
||||||
|
}) |
||||||
|
.on('mouseover', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
}) |
||||||
|
.on('mouseout', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
}); |
||||||
|
} |
||||||
|
redraw(): void { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
/** |
||||||
|
* 游戏状态 |
||||||
|
*/ |
||||||
|
export enum GameMode { |
||||||
|
BasicInformation, |
||||||
|
Assignment |
||||||
|
} |
@ -0,0 +1,246 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import { GameMode } from './gameMode'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 多点连线 |
||||||
|
*/ |
||||||
|
export class MultipointIcon extends PIXI.Container { |
||||||
|
public pointsData: PIXI.Point[]; |
||||||
|
public pointsGraphics: PIXI.Graphics[] = []; |
||||||
|
public iconsTilingSprite: PIXI.TilingSprite[] = []; |
||||||
|
style = new PIXI.TextStyle({ |
||||||
|
fontFamily: 'Arial', |
||||||
|
fontSize: 18, |
||||||
|
fontStyle: 'normal', |
||||||
|
fontWeight: 'bold', |
||||||
|
fill: ['#000000'], |
||||||
|
stroke: '#ffffff', |
||||||
|
strokeThickness: 3, |
||||||
|
dropShadow: true, |
||||||
|
dropShadowColor: '#000000', |
||||||
|
dropShadowBlur: 3, |
||||||
|
dropShadowAngle: Math.PI / 6, |
||||||
|
dropShadowDistance: 1, |
||||||
|
wordWrap: false, |
||||||
|
wordWrapWidth: 100, |
||||||
|
}); |
||||||
|
|
||||||
|
public text = new PIXI.Text(this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style); |
||||||
|
/** |
||||||
|
* |
||||||
|
* @param texture 图片素材 |
||||||
|
* @param points 点集合 |
||||||
|
*/ |
||||||
|
constructor(public assetData: any, private workingArea: WorkingAreaComponent) { |
||||||
|
super(); |
||||||
|
this.name = this.assetData.Id; |
||||||
|
this.pointsData = this.assetData.MultiPoint; |
||||||
|
this.x = this.assetData.Point.x; |
||||||
|
this.y = this.assetData.Point.y; |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
// 画线图标
|
||||||
|
for (let i = 0, count = this.pointsData.length - 1; i < count; i++) { |
||||||
|
const pointA = this.pointsData[i]; |
||||||
|
const pointB = this.pointsData[i + 1]; |
||||||
|
|
||||||
|
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI); |
||||||
|
const a = pointB.x - pointA.x; |
||||||
|
const b = pointB.y - pointA.y; |
||||||
|
const distance = Math.sqrt(a * a + b * b); |
||||||
|
|
||||||
|
const icon = new PIXI.TilingSprite(PIXI.Texture.from(this.assetData.ImageUrl), distance, 64); |
||||||
|
icon.anchor.set(0, 0.5); |
||||||
|
icon.x = pointA.x; |
||||||
|
icon.y = pointA.y; |
||||||
|
icon.angle = angle; |
||||||
|
icon.height = this.assetData.Thickness === 0 ? 32 : this.assetData.Thickness; |
||||||
|
this.iconsTilingSprite.push(icon); |
||||||
|
this.addChild(icon); |
||||||
|
if (i === 0) { |
||||||
|
this.text.anchor.set(0.5); |
||||||
|
this.text.position = icon.position; |
||||||
|
this.text.y -= this.assetData.Height; |
||||||
|
this.addChild(this.text); |
||||||
|
} |
||||||
|
} |
||||||
|
// 画点
|
||||||
|
this.pointsData.forEach((item, index, array) => { |
||||||
|
const iconPoint = new PIXI.Graphics(); |
||||||
|
iconPoint.lineStyle(1, 0xFFBD01, 1); |
||||||
|
iconPoint.beginFill(0xFFFFFF, 1); |
||||||
|
iconPoint.drawCircle(0, 0, 15); |
||||||
|
iconPoint.x = item.x; |
||||||
|
iconPoint.y = item.y; |
||||||
|
iconPoint.endFill(); |
||||||
|
iconPoint.visible = false; |
||||||
|
this.pointsGraphics.push(iconPoint); |
||||||
|
this.addChild(iconPoint); |
||||||
|
}); |
||||||
|
// 添加圆点事件
|
||||||
|
this.pointsGraphics.forEach((item, index, array) => { |
||||||
|
item.interactive = true; |
||||||
|
item.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) { |
||||||
|
event.currentTarget.data = event.data; |
||||||
|
event.currentTarget.alpha = 0.5; |
||||||
|
event.currentTarget.dragging = true; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseup', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseupoutside', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mousemove', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent); |
||||||
|
event.currentTarget.x = newPosition.x; |
||||||
|
event.currentTarget.y = newPosition.y; |
||||||
|
|
||||||
|
this.assetData.MultiPoint[index].x = newPosition.x; |
||||||
|
this.assetData.MultiPoint[index].y = newPosition.y; |
||||||
|
this.workingArea.canvasData.isChange = true; |
||||||
|
|
||||||
|
if (index === 0) {// 第一个点
|
||||||
|
this.iconsTilingSprite[index].x = newPosition.x; |
||||||
|
this.iconsTilingSprite[index].y = newPosition.y; |
||||||
|
|
||||||
|
const pointA = array[index]; |
||||||
|
const pointB = array[index + 1]; |
||||||
|
|
||||||
|
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI); |
||||||
|
const a = pointB.x - pointA.x; |
||||||
|
const b = pointB.y - pointA.y; |
||||||
|
const distance = Math.sqrt(a * a + b * b); |
||||||
|
this.iconsTilingSprite[index].angle = angle; |
||||||
|
this.iconsTilingSprite[index].width = distance; |
||||||
|
|
||||||
|
this.text.position = this.iconsTilingSprite[index].position; |
||||||
|
this.text.y -= this.assetData.Height; |
||||||
|
} else if (index < array.length - 1) {// 不是第一个点,也不是最后一个点
|
||||||
|
this.iconsTilingSprite[index].x = newPosition.x; |
||||||
|
this.iconsTilingSprite[index].y = newPosition.y; |
||||||
|
|
||||||
|
const pointA = array[index]; // 当前点
|
||||||
|
const pointB = array[index + 1]; // 后一个点
|
||||||
|
const pointC = array[index - 1]; // 前一个点
|
||||||
|
|
||||||
|
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI); |
||||||
|
const a = pointB.x - pointA.x; |
||||||
|
const b = pointB.y - pointA.y; |
||||||
|
const distance = Math.sqrt(a * a + b * b); |
||||||
|
this.iconsTilingSprite[index].angle = angle; |
||||||
|
this.iconsTilingSprite[index].width = distance; |
||||||
|
|
||||||
|
const angleC = Math.atan2((pointA.y - pointC.y), (pointA.x - pointC.x)) * (180 / Math.PI); |
||||||
|
const aC = pointA.x - pointC.x; |
||||||
|
const bC = pointA.y - pointC.y; |
||||||
|
const distanceC = Math.sqrt(aC * aC + bC * bC); |
||||||
|
this.iconsTilingSprite[index - 1].angle = angleC; |
||||||
|
this.iconsTilingSprite[index - 1].width = distanceC; |
||||||
|
} else if (index === array.length - 1) { // 最后一个点
|
||||||
|
const pointA = array[index]; // 当前点
|
||||||
|
const pointC = array[index - 1]; // 前一个点
|
||||||
|
|
||||||
|
const angleC = Math.atan2((pointA.y - pointC.y), (pointA.x - pointC.x)) * (180 / Math.PI); |
||||||
|
const aC = pointA.x - pointC.x; |
||||||
|
const bC = pointA.y - pointC.y; |
||||||
|
const distanceC = Math.sqrt(aC * aC + bC * bC); |
||||||
|
this.iconsTilingSprite[index - 1].angle = angleC; |
||||||
|
this.iconsTilingSprite[index - 1].width = distanceC; |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('rightclick', event => { |
||||||
|
}); |
||||||
|
}); |
||||||
|
// // 缩放
|
||||||
|
// this.workingArea.on('backgroundScale', data => {
|
||||||
|
// const scale = 1 / data;
|
||||||
|
// this.text.scale.set(scale);
|
||||||
|
// });
|
||||||
|
// 添加选中事件
|
||||||
|
this.iconsTilingSprite.forEach((item, index, array) => { |
||||||
|
item.interactive = true; |
||||||
|
item.buttonMode = true; |
||||||
|
item.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
this.workingArea.selection.selectOne(this); |
||||||
|
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) { |
||||||
|
event.currentTarget.parent.data = event.data; |
||||||
|
event.currentTarget.parent.alpha = 0.5; |
||||||
|
event.currentTarget.parent.dragging = true; |
||||||
|
|
||||||
|
event.currentTarget.parent.dragPoint = event.data.getLocalPosition(event.currentTarget.parent.parent); |
||||||
|
event.currentTarget.parent.dragPoint.x -= event.currentTarget.parent.x; |
||||||
|
event.currentTarget.parent.dragPoint.y -= event.currentTarget.parent.y; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseup', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
event.currentTarget.parent.alpha = 1; |
||||||
|
event.currentTarget.parent.dragging = false; |
||||||
|
event.currentTarget.parent.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseupoutside', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
event.currentTarget.parent.alpha = 1; |
||||||
|
event.currentTarget.parent.dragging = false; |
||||||
|
event.currentTarget.parent.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mousemove', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent); |
||||||
|
event.currentTarget.parent.x = newPosition.x - event.currentTarget.parent.dragPoint.x; |
||||||
|
event.currentTarget.parent.y = newPosition.y - event.currentTarget.parent.dragPoint.y; |
||||||
|
|
||||||
|
this.assetData.Point = new PIXI.Point(this.x, this.y); |
||||||
|
this.workingArea.canvasData.isChange = true; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('rightclick', event => { |
||||||
|
|
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 设置点显示状态 |
||||||
|
* @param value 显示状态 |
||||||
|
*/ |
||||||
|
public setPointVisiable(value: boolean) { |
||||||
|
this.pointsGraphics.forEach((item) => { |
||||||
|
item.visible = value; |
||||||
|
}); |
||||||
|
} |
||||||
|
// 设置名称
|
||||||
|
public setNameVisible(value: boolean, mode: GameMode) { |
||||||
|
if (this.assetData.GameMode === mode) { |
||||||
|
this.text.visible = value; |
||||||
|
} |
||||||
|
} |
||||||
|
// 刷新数据
|
||||||
|
public refresh() { |
||||||
|
console.log(this.assetData); |
||||||
|
this.iconsTilingSprite.forEach(element => { |
||||||
|
element.height = this.assetData.Thickness === 0 ? 32 : this.assetData.Thickness; |
||||||
|
}); |
||||||
|
this.text.text = this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
/** |
||||||
|
* 绘制模式 |
||||||
|
*/ |
||||||
|
export enum PaintMode { |
||||||
|
/** |
||||||
|
* 单点图标 |
||||||
|
*/ |
||||||
|
singlePointIcon, |
||||||
|
/** |
||||||
|
* 线段图标 |
||||||
|
*/ |
||||||
|
lineIcon, |
||||||
|
/** |
||||||
|
* 自定义多边形 |
||||||
|
*/ |
||||||
|
polygonIcon, |
||||||
|
/** |
||||||
|
* 水带多边形 |
||||||
|
*/ |
||||||
|
Pipeline, |
||||||
|
/** |
||||||
|
* 结束绘制 |
||||||
|
*/ |
||||||
|
endPaint, |
||||||
|
/** |
||||||
|
* 暂无 |
||||||
|
*/ |
||||||
|
Arrows, |
||||||
|
/** |
||||||
|
* 暂无 |
||||||
|
*/ |
||||||
|
Car, |
||||||
|
} |
@ -0,0 +1,328 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
import { AxShape } from './axShape'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 管线 |
||||||
|
*/ |
||||||
|
export class Pipeline extends AxShape { |
||||||
|
public line: PIXI.Graphics = new PIXI.Graphics(); |
||||||
|
constructor(assetData: any, workingArea: WorkingAreaComponent) { |
||||||
|
super(assetData, workingArea); |
||||||
|
this.name = this.assetData.Id; |
||||||
|
this.moveable = false; |
||||||
|
this.x = this.assetData.Point.x; |
||||||
|
this.y = this.assetData.Point.y; |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
this.addChild(this.line); |
||||||
|
// 画线图标
|
||||||
|
this.refresh(); |
||||||
|
this.interactive = true; |
||||||
|
this.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
this.workingArea.selection.selectOne(this); |
||||||
|
}); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 刷新 |
||||||
|
*/ |
||||||
|
public refresh() { |
||||||
|
|
||||||
|
const strokeWidth = 1; |
||||||
|
const startWidth = 30 + strokeWidth; |
||||||
|
const endWidth = 30 + strokeWidth; |
||||||
|
const edgeWidth = 10; |
||||||
|
const openEnded = false; |
||||||
|
const markerStart = false; |
||||||
|
const markerEnd = true; |
||||||
|
const spacing = (openEnded) ? 0 : 0 + strokeWidth / 2; |
||||||
|
const startSize = 30 + strokeWidth; |
||||||
|
const endSize = 30 + strokeWidth; |
||||||
|
const isRounded = true; |
||||||
|
const pts = this.assetData.MultiPoint; |
||||||
|
const c = this.line; |
||||||
|
if (pts.length < 2) { return; } |
||||||
|
// Base vector (between first points)
|
||||||
|
const pe = pts[pts.length - 1]; |
||||||
|
|
||||||
|
// Finds first non-overlapping point
|
||||||
|
let i0 = 1; |
||||||
|
|
||||||
|
while (i0 < pts.length - 1 && pts[i0].x === pts[0].x && pts[i0].y === pts[0].y) { |
||||||
|
i0++; |
||||||
|
} |
||||||
|
|
||||||
|
const dx = pts[i0].x - pts[0].x; |
||||||
|
const dy = pts[i0].y - pts[0].y; |
||||||
|
const dist = Math.sqrt(dx * dx + dy * dy); |
||||||
|
|
||||||
|
if (dist === 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Computes the norm and the inverse norm
|
||||||
|
let nx = dx / dist; |
||||||
|
let nx1 = nx; |
||||||
|
let nx2 = nx; |
||||||
|
let ny = dy / dist; |
||||||
|
let ny2 = ny; |
||||||
|
let ny1 = ny; |
||||||
|
let orthx = edgeWidth * ny; |
||||||
|
let orthy = -edgeWidth * nx; |
||||||
|
|
||||||
|
// Stores the inbound function calls in reverse order in fns
|
||||||
|
const fns = []; |
||||||
|
|
||||||
|
// if (isRounded) {
|
||||||
|
// // c.setLineJoin('round');
|
||||||
|
// c.lineTextureStyle({ join: PIXI.LINE_JOIN.ROUND });
|
||||||
|
// } else if (pts.length > 2) {
|
||||||
|
// // Only mitre if there are waypoints
|
||||||
|
// // c.setMiterLimit(1.42);
|
||||||
|
// c.lineTextureStyle({ miterLimit: 1.42 });
|
||||||
|
// }
|
||||||
|
// c.lineStyle(1, 0x000000, 1);
|
||||||
|
c.clear(); |
||||||
|
c.lineTextureStyle({ width: 1, color: 0x00000, join: PIXI.LINE_JOIN.ROUND }); |
||||||
|
// c.begin();
|
||||||
|
c.beginFill(0xffffff); |
||||||
|
const startNx = nx; |
||||||
|
const startNy = ny; |
||||||
|
|
||||||
|
if (markerStart && !openEnded) { |
||||||
|
this.paintMarker(c, pts[0].x, pts[0].y, nx, ny, startSize, startWidth, edgeWidth, spacing, true); |
||||||
|
} else { |
||||||
|
const outStartX = pts[0].x + orthx / 2 + spacing * nx; |
||||||
|
const outStartY = pts[0].y + orthy / 2 + spacing * ny; |
||||||
|
const inEndX = pts[0].x - orthx / 2 + spacing * nx; |
||||||
|
const inEndY = pts[0].y - orthy / 2 + spacing * ny; |
||||||
|
|
||||||
|
if (openEnded) { |
||||||
|
c.moveTo(outStartX, outStartY); |
||||||
|
fns.push( () => { |
||||||
|
c.lineTo(inEndX, inEndY); |
||||||
|
}); |
||||||
|
} else { |
||||||
|
c.moveTo(inEndX, inEndY); |
||||||
|
c.lineTo(outStartX, outStartY); |
||||||
|
} |
||||||
|
} |
||||||
|
let dx1 = 0; |
||||||
|
let dy1 = 0; |
||||||
|
let dist1 = 0; |
||||||
|
|
||||||
|
for (let i = 0; i < pts.length - 2; i++) { |
||||||
|
// Work out in which direction the line is bending
|
||||||
|
const pos = this.relativeCcw(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, pts[i + 2].x, pts[i + 2].y); |
||||||
|
|
||||||
|
dx1 = pts[i + 2].x - pts[i + 1].x; |
||||||
|
dy1 = pts[i + 2].y - pts[i + 1].y; |
||||||
|
|
||||||
|
dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); |
||||||
|
|
||||||
|
if (dist1 !== 0) { |
||||||
|
nx1 = dx1 / dist1; |
||||||
|
ny1 = dy1 / dist1; |
||||||
|
|
||||||
|
const tmp1 = nx * nx1 + ny * ny1; |
||||||
|
const tmp = Math.max(Math.sqrt((tmp1 + 1) / 2), 0.04); |
||||||
|
|
||||||
|
// Work out the normal orthogonal to the line through the control point and the edge sides intersection
|
||||||
|
nx2 = (nx + nx1); |
||||||
|
ny2 = (ny + ny1); |
||||||
|
|
||||||
|
const dist2 = Math.sqrt(nx2 * nx2 + ny2 * ny2); |
||||||
|
|
||||||
|
if (dist2 !== 0) { |
||||||
|
nx2 = nx2 / dist2; |
||||||
|
ny2 = ny2 / dist2; |
||||||
|
|
||||||
|
// Higher strokewidths require a larger minimum bend, 0.35 covers all but the most extreme cases
|
||||||
|
const strokeWidthFactor = Math.max(tmp, Math.min(1 / 200 + 0.04, 0.35)); |
||||||
|
const angleFactor = (pos !== 0 && isRounded) ? Math.max(0.1, strokeWidthFactor) : Math.max(tmp, 0.06); |
||||||
|
|
||||||
|
const outX = pts[i + 1].x + ny2 * edgeWidth / 2 / angleFactor; |
||||||
|
const outY = pts[i + 1].y - nx2 * edgeWidth / 2 / angleFactor; |
||||||
|
const inX = pts[i + 1].x - ny2 * edgeWidth / 2 / angleFactor; |
||||||
|
const inY = pts[i + 1].y + nx2 * edgeWidth / 2 / angleFactor; |
||||||
|
|
||||||
|
if (pos === 0 || !isRounded) { |
||||||
|
// If the two segments are aligned, or if we're not drawing curved sections between segments
|
||||||
|
// just draw straight to the intersection point
|
||||||
|
c.lineTo(outX, outY); |
||||||
|
|
||||||
|
((x, y) => { |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(x, y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} else if (pos === -1) { |
||||||
|
const c1x = inX + ny * edgeWidth; |
||||||
|
const c1y = inY - nx * edgeWidth; |
||||||
|
const c2x = inX + ny1 * edgeWidth; |
||||||
|
const c2y = inY - nx1 * edgeWidth; |
||||||
|
c.lineTo(c1x, c1y); |
||||||
|
if (isRounded) { |
||||||
|
c.quadraticCurveTo(outX, outY, c2x, c2y); // 圆角
|
||||||
|
} else { |
||||||
|
c.lineTo(outX, outY); |
||||||
|
} |
||||||
|
((x, y) => { |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(x, y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} else { |
||||||
|
c.lineTo(outX, outY); |
||||||
|
|
||||||
|
((x, y) => { |
||||||
|
const c1x = outX - ny * edgeWidth; |
||||||
|
const c1y = outY + nx * edgeWidth; |
||||||
|
const c2x = outX - ny1 * edgeWidth; |
||||||
|
const c2y = outY + nx1 * edgeWidth; |
||||||
|
|
||||||
|
fns.push(() => { |
||||||
|
if (isRounded) { |
||||||
|
c.quadraticCurveTo(x, y, c1x, c1y); |
||||||
|
} else { |
||||||
|
c.lineTo(x, y); |
||||||
|
} |
||||||
|
}); |
||||||
|
fns.push(() => { |
||||||
|
c.lineTo(c2x, c2y); |
||||||
|
}); |
||||||
|
})(inX, inY); |
||||||
|
} |
||||||
|
|
||||||
|
nx = nx1; |
||||||
|
ny = ny1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
orthx = edgeWidth * ny1; |
||||||
|
orthy = - edgeWidth * nx1; |
||||||
|
|
||||||
|
if (markerEnd && !openEnded) { |
||||||
|
this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, false); |
||||||
|
} else { |
||||||
|
c.lineTo(pe.x - spacing * nx1 + orthx / 2, pe.y - spacing * ny1 + orthy / 2); |
||||||
|
|
||||||
|
const inStartX = pe.x - spacing * nx1 - orthx / 2; |
||||||
|
const inStartY = pe.y - spacing * ny1 - orthy / 2; |
||||||
|
|
||||||
|
if (!openEnded) { |
||||||
|
c.lineTo(inStartX, inStartY); |
||||||
|
} else { |
||||||
|
c.moveTo(inStartX, inStartY); |
||||||
|
|
||||||
|
fns.splice(0, 0, () => { |
||||||
|
c.moveTo(inStartX, inStartY); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (let i = fns.length - 1; i >= 0; i--) { |
||||||
|
fns[i](); |
||||||
|
} |
||||||
|
c.closePath(); |
||||||
|
c.endFill(); |
||||||
|
// if (openEnded)
|
||||||
|
// {
|
||||||
|
// c.end();
|
||||||
|
// c.stroke();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// c.close();
|
||||||
|
// c.fillAndStroke();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Workaround for shadow on top of base arrow
|
||||||
|
// c.setShadow(false);
|
||||||
|
|
||||||
|
// Need to redraw the markers without the low miter limit
|
||||||
|
// c.setMiterLimit(4);
|
||||||
|
|
||||||
|
// if (isRounded)
|
||||||
|
// {
|
||||||
|
// c.setLineJoin('flat');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (pts.length > 2) {
|
||||||
|
// // Only to repaint markers if no waypoints
|
||||||
|
// // Need to redraw the markers without the low miter limit
|
||||||
|
// // c.setMiterLimit(4);
|
||||||
|
// c.lineTextureStyle({ width: 1, color: 0x00000, miterLimit: 4 });
|
||||||
|
// if (markerStart && !openEnded) {
|
||||||
|
// // c.begin();
|
||||||
|
// this.paintMarker(c, pts[0].x, pts[0].y, startNx, startNy, startSize, startWidth, edgeWidth, spacing, true);
|
||||||
|
// // c.stroke();
|
||||||
|
// // c.end();
|
||||||
|
// // c.closePath();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (markerEnd && !openEnded) {
|
||||||
|
// // c.begin();
|
||||||
|
// this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, true);
|
||||||
|
// // c.stroke();
|
||||||
|
// // c.end();
|
||||||
|
// // c.closePath();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} |
||||||
|
/** |
||||||
|
* 画箭头 |
||||||
|
* @param c |
||||||
|
* @param ptX |
||||||
|
* @param ptY |
||||||
|
* @param nx |
||||||
|
* @param ny |
||||||
|
* @param size |
||||||
|
* @param arrowWidth |
||||||
|
* @param edgeWidth |
||||||
|
* @param spacing |
||||||
|
* @param initialMove |
||||||
|
*/ |
||||||
|
paintMarker(c: PIXI.Graphics, ptX: number, ptY: number, nx: number, ny: number, |
||||||
|
size: number, arrowWidth: number, edgeWidth: number, spacing: number, initialMove: boolean) { |
||||||
|
const widthArrowRatio = edgeWidth / arrowWidth; |
||||||
|
const orthx = edgeWidth * ny / 2; |
||||||
|
const orthy = -edgeWidth * nx / 2; |
||||||
|
|
||||||
|
const spaceX = (spacing + size) * nx; |
||||||
|
const spaceY = (spacing + size) * ny; |
||||||
|
|
||||||
|
if (initialMove) { |
||||||
|
c.moveTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
||||||
|
} else { |
||||||
|
c.lineTo(ptX - orthx + spaceX, ptY - orthy + spaceY); |
||||||
|
} |
||||||
|
c.lineTo(ptX - orthx / widthArrowRatio + spaceX, ptY - orthy / widthArrowRatio + spaceY); |
||||||
|
c.lineTo(ptX + spacing * nx, ptY + spacing * ny); |
||||||
|
c.lineTo(ptX + orthx / widthArrowRatio + spaceX, ptY + orthy / widthArrowRatio + spaceY); |
||||||
|
c.lineTo(ptX + orthx + spaceX, ptY + orthy + spaceY); |
||||||
|
} |
||||||
|
|
||||||
|
relativeCcw(x1: number, y1: number, x2: number, y2: number, px: number, py: number) { |
||||||
|
x2 -= x1; |
||||||
|
y2 -= y1; |
||||||
|
px -= x1; |
||||||
|
py -= y1; |
||||||
|
let ccw = px * y2 - py * x2; |
||||||
|
|
||||||
|
if (ccw === 0.0) { |
||||||
|
ccw = px * x2 + py * y2; |
||||||
|
|
||||||
|
if (ccw > 0.0) { |
||||||
|
px -= x2; |
||||||
|
py -= y2; |
||||||
|
ccw = px * x2 + py * y2; |
||||||
|
|
||||||
|
if (ccw < 0.0) { |
||||||
|
ccw = 0.0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,269 @@ |
|||||||
|
import { WorkingAreaComponent } from '../working-area.component'; |
||||||
|
import { GameMode } from './gameMode'; |
||||||
|
import * as PIXI from 'pixi.js'; |
||||||
|
import { PaintMode } from './paintModel'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 多边形 |
||||||
|
*/ |
||||||
|
export class PolygonIcon extends PIXI.Container { |
||||||
|
public pointsData: PIXI.Point[]; |
||||||
|
public pointsGraphics: PIXI.Graphics[] = []; |
||||||
|
public polygonGraphics: PIXI.Graphics = new PIXI.Graphics(); |
||||||
|
public polygonLineGraphics: PIXI.Graphics = new PIXI.Graphics(); |
||||||
|
style = new PIXI.TextStyle({ |
||||||
|
fontFamily: 'Arial', |
||||||
|
fontSize: 18, |
||||||
|
fontStyle: 'normal', |
||||||
|
fontWeight: 'bold', |
||||||
|
fill: ['#000000'], |
||||||
|
stroke: '#ffffff', |
||||||
|
strokeThickness: 3, |
||||||
|
dropShadow: true, |
||||||
|
dropShadowColor: '#000000', |
||||||
|
dropShadowBlur: 3, |
||||||
|
dropShadowAngle: Math.PI / 6, |
||||||
|
dropShadowDistance: 1, |
||||||
|
wordWrap: false, |
||||||
|
wordWrapWidth: 100, |
||||||
|
}); |
||||||
|
|
||||||
|
public text = new PIXI.Text(this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style); |
||||||
|
/** |
||||||
|
* |
||||||
|
* @param points 点集合 |
||||||
|
*/ |
||||||
|
constructor(public assetData: any, private workingArea: WorkingAreaComponent) { |
||||||
|
super(); |
||||||
|
this.name = this.assetData.Id; |
||||||
|
this.x = this.assetData.Point.x; |
||||||
|
this.y = this.assetData.Point.y; |
||||||
|
this.pointsData = this.assetData.MultiPoint; |
||||||
|
this.workingArea.backgroundImage.addChild(this); |
||||||
|
this.sortableChildren = true; |
||||||
|
// 画点
|
||||||
|
this.pointsData.forEach((item, index, array) => { |
||||||
|
const iconPoint = new PIXI.Graphics(); |
||||||
|
iconPoint.lineStyle(1, 0xFFBD01, 1); |
||||||
|
iconPoint.beginFill(0xFFFFFF, 1); |
||||||
|
iconPoint.drawCircle(0, 0, 15); |
||||||
|
iconPoint.x = item.x; |
||||||
|
iconPoint.y = item.y; |
||||||
|
iconPoint.endFill(); |
||||||
|
iconPoint.visible = false; |
||||||
|
this.pointsGraphics.push(iconPoint); |
||||||
|
this.addChild(iconPoint); |
||||||
|
}); |
||||||
|
// 填充多边形
|
||||||
|
|
||||||
|
const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x'); |
||||||
|
const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255; |
||||||
|
this.polygonGraphics.beginFill(color, angle); |
||||||
|
this.polygonGraphics.drawPolygon(this.getPoints()); |
||||||
|
this.polygonGraphics.endFill(); |
||||||
|
this.addChild(this.polygonGraphics); |
||||||
|
// 画多边形
|
||||||
|
this.polygonLineGraphics.lineStyle(5, 0xFFBD01, 1); |
||||||
|
this.polygonLineGraphics.drawPolygon(this.getPoints()); |
||||||
|
this.polygonLineGraphics.closePath(); |
||||||
|
this.addChild(this.polygonLineGraphics); |
||||||
|
|
||||||
|
this.text.anchor.set(0.5); |
||||||
|
this.text.position = this.calculatePolygonGravityCenter(this.pointsData); |
||||||
|
// console.log(this.calculatePolygonGravityCenter(this.pointsData));
|
||||||
|
this.polygonGraphics.addChild(this.text); |
||||||
|
// 添加圆点事件
|
||||||
|
this.pointsGraphics.forEach((item, index, array) => { |
||||||
|
item.interactive = true; |
||||||
|
item.buttonMode = true; |
||||||
|
item.zIndex = 1; |
||||||
|
item.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) { |
||||||
|
event.currentTarget.data = event.data; |
||||||
|
event.currentTarget.alpha = 0.5; |
||||||
|
event.currentTarget.dragging = true; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseup', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseupoutside', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
event.currentTarget.alpha = 1; |
||||||
|
event.currentTarget.dragging = false; |
||||||
|
event.currentTarget.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mousemove', event => { |
||||||
|
if (event.currentTarget.dragging) { |
||||||
|
const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent); |
||||||
|
event.currentTarget.x = newPosition.x; |
||||||
|
event.currentTarget.y = newPosition.y; |
||||||
|
|
||||||
|
this.assetData.MultiPoint[index].x = newPosition.x; |
||||||
|
this.assetData.MultiPoint[index].y = newPosition.y; |
||||||
|
this.workingArea.canvasData.isChange = true; |
||||||
|
// 填充多边形
|
||||||
|
this.polygonGraphics.clear(); |
||||||
|
this.polygonGraphics.beginFill(color, angle); |
||||||
|
this.polygonGraphics.drawPolygon(this.getPoints()); |
||||||
|
this.polygonGraphics.endFill(); |
||||||
|
// 画多边形
|
||||||
|
this.polygonLineGraphics.clear(); |
||||||
|
this.polygonLineGraphics.lineStyle(5, 0xFFBD01, 1); |
||||||
|
this.polygonLineGraphics.drawPolygon(this.getPoints()); |
||||||
|
this.polygonLineGraphics.closePath(); |
||||||
|
|
||||||
|
this.text.position = this.calculatePolygonGravityCenter(this.pointsData); |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('rightclick', event => { |
||||||
|
}) .on('mouseover', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.previewImage !== null |
||||||
|
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) { |
||||||
|
this.workingArea.previewImage.visible = false; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseout', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.previewImage !== null |
||||||
|
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) { |
||||||
|
this.workingArea.previewImage.visible = true; |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
// 添加选中事件
|
||||||
|
this.polygonGraphics.interactive = true; |
||||||
|
this.polygonGraphics.buttonMode = true; |
||||||
|
this.polygonGraphics |
||||||
|
.on('mousedown', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
this.workingArea.selection.selectOne(this); |
||||||
|
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) { |
||||||
|
event.currentTarget.parent.data = event.data; |
||||||
|
event.currentTarget.parent.alpha = 0.5; |
||||||
|
event.currentTarget.parent.dragging = true; |
||||||
|
|
||||||
|
event.currentTarget.parent.dragPoint = event.data.getLocalPosition(event.currentTarget.parent.parent); |
||||||
|
event.currentTarget.parent.dragPoint.x -= event.currentTarget.parent.x; |
||||||
|
event.currentTarget.parent.dragPoint.y -= event.currentTarget.parent.y; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseup', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
event.currentTarget.parent.alpha = 1; |
||||||
|
event.currentTarget.parent.dragging = false; |
||||||
|
event.currentTarget.parent.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseupoutside', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
event.currentTarget.parent.alpha = 1; |
||||||
|
event.currentTarget.parent.dragging = false; |
||||||
|
event.currentTarget.parent.data = null; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mousemove', event => { |
||||||
|
if (event.currentTarget.parent.dragging) { |
||||||
|
const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent); |
||||||
|
event.currentTarget.parent.x = newPosition.x - event.currentTarget.parent.dragPoint.x; |
||||||
|
event.currentTarget.parent.y = newPosition.y - event.currentTarget.parent.dragPoint.y; |
||||||
|
|
||||||
|
this.assetData.Point = new PIXI.Point(this.x, this.y); |
||||||
|
this.workingArea.canvasData.isChange = true; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('rightclick', event => { |
||||||
|
// this.workingArea.selection.deselectAll();
|
||||||
|
}) |
||||||
|
.on('mouseover', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.previewImage !== null |
||||||
|
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) { |
||||||
|
this.workingArea.previewImage.visible = false; |
||||||
|
} |
||||||
|
}) |
||||||
|
.on('mouseout', event => { |
||||||
|
event.stopPropagation(); |
||||||
|
if (this.workingArea.previewImage !== null |
||||||
|
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) { |
||||||
|
this.workingArea.previewImage.visible = true; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 设置点显示状态 |
||||||
|
* @param value 显示状态 |
||||||
|
*/ |
||||||
|
public setPointVisiable(value: boolean) { |
||||||
|
this.pointsGraphics.forEach((item) => { |
||||||
|
item.visible = value; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public calculatePolygonGravityCenter(points: PIXI.Point[]) { |
||||||
|
let area = 0.0; // 多边形面积
|
||||||
|
let gravityLat = 0.0; // 重心点 latitude
|
||||||
|
let gravityLng = 0.0; // 重心点 longitude
|
||||||
|
points.forEach((item, index) => { |
||||||
|
// 1
|
||||||
|
const lat = item.x; |
||||||
|
const lng = item.y; |
||||||
|
const nextLat = points[(index + 1) % points.length].x; |
||||||
|
const nextLng = points[(index + 1) % points.length].y; |
||||||
|
// 2
|
||||||
|
const tempArea = (nextLat * lng - nextLng * lat) / 2.0; |
||||||
|
// 3
|
||||||
|
area += tempArea; |
||||||
|
// 4
|
||||||
|
gravityLat += tempArea * (lat + nextLat) / 3; |
||||||
|
gravityLng += tempArea * (lng + nextLng) / 3; |
||||||
|
}); |
||||||
|
// 5
|
||||||
|
gravityLat = gravityLat / area; |
||||||
|
gravityLng = gravityLng / area; |
||||||
|
|
||||||
|
return new PIXI.Point(gravityLat, gravityLng); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 获取点集合 |
||||||
|
*/ |
||||||
|
public getPoints(): PIXI.Point[] { |
||||||
|
const points: PIXI.Point[] = []; |
||||||
|
this.pointsGraphics.forEach(item => { |
||||||
|
points.push(item.position); |
||||||
|
}); |
||||||
|
return points; |
||||||
|
} |
||||||
|
/** |
||||||
|
* 设置名称显示 |
||||||
|
* @param value true/false 显示/隐藏 |
||||||
|
* @param mode BasicInformation = 0 基本信息 |
||||||
|
* Assignment想定作业 = 1 想定作业 |
||||||
|
*/ |
||||||
|
public setNameVisible(value: boolean, mode: GameMode) { |
||||||
|
if (this.assetData.GameMode === mode) { |
||||||
|
this.text.visible = value; |
||||||
|
} |
||||||
|
} |
||||||
|
public refresh() { |
||||||
|
this.text.text = this.assetData.Name |
||||||
|
+ '\r\n' |
||||||
|
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue; |
||||||
|
// 填充多边形
|
||||||
|
const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x'); |
||||||
|
const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255; |
||||||
|
this.polygonGraphics.clear(); |
||||||
|
this.polygonGraphics.beginFill(color, angle); |
||||||
|
this.polygonGraphics.drawPolygon(this.getPoints()); |
||||||
|
this.polygonGraphics.endFill(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
// import { OldFilmFilter } from 'pixi-filters';
|
||||||
|
// import { WorkingAreaComponent } from '../working-area.component';
|
||||||
|
// import { PaintMode } from './paintModel';
|
||||||
|
// import { SinglePointIcon } from './axImageShape';
|
||||||
|
// import * as PIXI from 'pixi.js';
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 汽车放置区域
|
||||||
|
// */
|
||||||
|
// export class PutCarArea extends PIXI.Container {
|
||||||
|
// public polygonGraphics: PIXI.Graphics = new PIXI.Graphics();
|
||||||
|
// constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
|
||||||
|
// super();
|
||||||
|
// this.name = this.assetData.Id;
|
||||||
|
// this.x = this.assetData.Point.x;
|
||||||
|
// this.y = this.assetData.Point.y;
|
||||||
|
// this.workingArea.backgroundImage.addChild(this);
|
||||||
|
// this.sortableChildren = true;
|
||||||
|
|
||||||
|
// // 填充多边形
|
||||||
|
|
||||||
|
// const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x');
|
||||||
|
// const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255;
|
||||||
|
// this.polygonGraphics.beginFill(color, angle);
|
||||||
|
// this.polygonGraphics.drawPolygon(this.assetData.MultiPoint);
|
||||||
|
// this.polygonGraphics.endFill();
|
||||||
|
// this.addChild(this.polygonGraphics);
|
||||||
|
// // 添加选中事件
|
||||||
|
// this.polygonGraphics.interactive = true;
|
||||||
|
// this.polygonGraphics
|
||||||
|
// .on('pointerdown', (event) => {
|
||||||
|
// if (this.workingArea.getPaintMode() === PaintMode.Car) {
|
||||||
|
// this.workingArea.selectCar.Point =
|
||||||
|
// new PIXI.Point(this.workingArea.previewSinglePointIcon.x, this.workingArea.previewSinglePointIcon.y);
|
||||||
|
// this.workingArea.selectCar.Angle = this.assetData.Direction;
|
||||||
|
// const car = new SinglePointIcon(this.workingArea.selectCar, this.workingArea);
|
||||||
|
// this.workingArea.setPaintMode(PaintMode.endPaint);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .on('pointerup', (event) => {
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .on('pointerupoutside', (event) => {
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .on('pointerover', (event) => {
|
||||||
|
// this.workingArea.previewSinglePointIcon.filters = null;
|
||||||
|
// this.workingArea.previewSinglePointIcon.zIndex = this.zIndex + 1;
|
||||||
|
// // 设置车辆方向
|
||||||
|
// this.workingArea.previewSinglePointIcon.angle = this.assetData.Direction;
|
||||||
|
// console.log(this.assetData.Name);
|
||||||
|
// })
|
||||||
|
// .on('pointerout', (event) => {
|
||||||
|
// this.workingArea.previewSinglePointIcon.filters = [
|
||||||
|
// new OldFilmFilter()
|
||||||
|
// ];
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 2.1 MiB |
Loading…
Reference in new issue