|
|
@@ -1043,25 +1043,44 @@ export function getRotatedCorners(b: Bounds, rotation: number) {
|
|
1043
|
1043
|
|
|
1044
|
1044
|
export function getTransformedBoundingBox(
|
|
1045
|
1045
|
bounds: Bounds,
|
|
1046
|
|
- handle: TransformCorner | TransformEdge,
|
|
|
1046
|
+ handle: TransformCorner | TransformEdge | "center",
|
|
1047
|
1047
|
delta: number[],
|
|
1048
|
|
- rotation = 0
|
|
|
1048
|
+ rotation = 0,
|
|
|
1049
|
+ isAspectRatioLocked = false
|
|
1049
|
1050
|
) {
|
|
1050
|
1051
|
// Create top left and bottom right corners.
|
|
1051
|
1052
|
let [ax0, ay0] = [bounds.minX, bounds.minY]
|
|
1052
|
1053
|
let [ax1, ay1] = [bounds.maxX, bounds.maxY]
|
|
1053
|
1054
|
|
|
1054
|
|
- // Create a second set of corners for the result.
|
|
|
1055
|
+ // Create a second set of corners for the new box.
|
|
1055
|
1056
|
let [bx0, by0] = [bounds.minX, bounds.minY]
|
|
1056
|
1057
|
let [bx1, by1] = [bounds.maxX, bounds.maxY]
|
|
1057
|
1058
|
|
|
|
1059
|
+ // If the drag is on the center, just translate the bounds.
|
|
|
1060
|
+ if (handle === "center") {
|
|
|
1061
|
+ return {
|
|
|
1062
|
+ minX: bx0 + delta[0],
|
|
|
1063
|
+ minY: by0 + delta[1],
|
|
|
1064
|
+ maxX: bx1 + delta[0],
|
|
|
1065
|
+ maxY: by1 + delta[1],
|
|
|
1066
|
+ width: bx1 - bx0,
|
|
|
1067
|
+ height: by1 - by0,
|
|
|
1068
|
+ scaleX: 1,
|
|
|
1069
|
+ scaleY: 1,
|
|
|
1070
|
+ }
|
|
|
1071
|
+ }
|
|
|
1072
|
+
|
|
1058
|
1073
|
// Counter rotate the delta. This lets us make changes as if
|
|
1059
|
1074
|
// the (possibly rotated) boxes were axis aligned.
|
|
1060
|
|
- const [dx, dy] = vec.rot(delta, -rotation)
|
|
|
1075
|
+ let [dx, dy] = vec.rot(delta, -rotation)
|
|
1061
|
1076
|
|
|
1062
|
|
- // Depending on the dragging handle (an edge or corner of
|
|
1063
|
|
- // the bounding box), use the delta to adjust the result's corners.
|
|
|
1077
|
+ /*
|
|
|
1078
|
+ 1. Delta
|
|
1064
|
1079
|
|
|
|
1080
|
+ Use the delta to adjust the new box by changing its corners.
|
|
|
1081
|
+ The dragging handle (corner or edge) will determine which
|
|
|
1082
|
+ corners should change.
|
|
|
1083
|
+ */
|
|
1065
|
1084
|
switch (handle) {
|
|
1066
|
1085
|
case TransformEdge.Top:
|
|
1067
|
1086
|
case TransformCorner.TopLeft:
|
|
|
@@ -1092,10 +1111,76 @@ export function getTransformedBoundingBox(
|
|
1092
|
1111
|
}
|
|
1093
|
1112
|
}
|
|
1094
|
1113
|
|
|
1095
|
|
- // If the bounds are rotated, get a vector from the rotated anchor
|
|
1096
|
|
- // corner in the inital bounds to the rotated anchor corner in the
|
|
1097
|
|
- // result's bounds. Subtract this vector from the result's corners,
|
|
1098
|
|
- // so that the two anchor points (initial and result) will be equal.
|
|
|
1114
|
+ const aw = ax1 - ax0
|
|
|
1115
|
+ const ah = ay1 - ay0
|
|
|
1116
|
+
|
|
|
1117
|
+ const scaleX = (bx1 - bx0) / aw
|
|
|
1118
|
+ const scaleY = (by1 - by0) / ah
|
|
|
1119
|
+
|
|
|
1120
|
+ const bw = Math.abs(bx1 - bx0)
|
|
|
1121
|
+ const bh = Math.abs(by1 - by0)
|
|
|
1122
|
+
|
|
|
1123
|
+ /*
|
|
|
1124
|
+ 2. Aspect ratio
|
|
|
1125
|
+
|
|
|
1126
|
+ If the aspect ratio is locked, adjust the corners so that the
|
|
|
1127
|
+ new box's aspect ratio matches the original aspect ratio.
|
|
|
1128
|
+ */
|
|
|
1129
|
+
|
|
|
1130
|
+ if (isAspectRatioLocked) {
|
|
|
1131
|
+ const ar = aw / ah
|
|
|
1132
|
+ const isTall = ar < bw / bh
|
|
|
1133
|
+ const tw = bw * (scaleY < 0 ? 1 : -1) * (1 / ar)
|
|
|
1134
|
+ const th = bh * (scaleX < 0 ? 1 : -1) * ar
|
|
|
1135
|
+
|
|
|
1136
|
+ switch (handle) {
|
|
|
1137
|
+ case TransformCorner.TopLeft: {
|
|
|
1138
|
+ if (isTall) by0 = by1 + tw
|
|
|
1139
|
+ else bx0 = bx1 + th
|
|
|
1140
|
+ break
|
|
|
1141
|
+ }
|
|
|
1142
|
+ case TransformCorner.TopRight: {
|
|
|
1143
|
+ if (isTall) by0 = by1 + tw
|
|
|
1144
|
+ else bx1 = bx0 - th
|
|
|
1145
|
+ break
|
|
|
1146
|
+ }
|
|
|
1147
|
+ case TransformCorner.BottomRight: {
|
|
|
1148
|
+ if (isTall) by1 = by0 - tw
|
|
|
1149
|
+ else bx1 = bx0 - th
|
|
|
1150
|
+ break
|
|
|
1151
|
+ }
|
|
|
1152
|
+ case TransformCorner.BottomLeft: {
|
|
|
1153
|
+ if (isTall) by1 = by0 - tw
|
|
|
1154
|
+ else bx0 = bx1 + th
|
|
|
1155
|
+ break
|
|
|
1156
|
+ }
|
|
|
1157
|
+ case TransformEdge.Bottom:
|
|
|
1158
|
+ case TransformEdge.Top: {
|
|
|
1159
|
+ const m = (bx0 + bx1) / 2
|
|
|
1160
|
+ const w = bh * ar
|
|
|
1161
|
+ bx0 = m - w / 2
|
|
|
1162
|
+ bx1 = m + w / 2
|
|
|
1163
|
+ break
|
|
|
1164
|
+ }
|
|
|
1165
|
+ case TransformEdge.Left:
|
|
|
1166
|
+ case TransformEdge.Right: {
|
|
|
1167
|
+ const m = (by0 + by1) / 2
|
|
|
1168
|
+ const h = bw / ar
|
|
|
1169
|
+ by0 = m - h / 2
|
|
|
1170
|
+ by1 = m + h / 2
|
|
|
1171
|
+ break
|
|
|
1172
|
+ }
|
|
|
1173
|
+ }
|
|
|
1174
|
+ }
|
|
|
1175
|
+
|
|
|
1176
|
+ /*
|
|
|
1177
|
+ 3. Rotation
|
|
|
1178
|
+
|
|
|
1179
|
+ If the bounds are rotated, get a vector from the rotated anchor
|
|
|
1180
|
+ corner in the inital bounds to the rotated anchor corner in the
|
|
|
1181
|
+ result's bounds. Subtract this vector from the result's corners,
|
|
|
1182
|
+ so that the two anchor points (initial and result) will be equal.
|
|
|
1183
|
+ */
|
|
1099
|
1184
|
|
|
1100
|
1185
|
if (rotation % (Math.PI * 2) !== 0) {
|
|
1101
|
1186
|
let cv = [0, 0]
|
|
|
@@ -1104,9 +1189,7 @@ export function getTransformedBoundingBox(
|
|
1104
|
1189
|
const c1 = vec.med([bx0, by0], [bx1, by1])
|
|
1105
|
1190
|
|
|
1106
|
1191
|
switch (handle) {
|
|
1107
|
|
- case TransformCorner.TopLeft:
|
|
1108
|
|
- case TransformEdge.Top:
|
|
1109
|
|
- case TransformEdge.Left: {
|
|
|
1192
|
+ case TransformCorner.TopLeft: {
|
|
1110
|
1193
|
cv = vec.sub(
|
|
1111
|
1194
|
vec.rotWith([bx1, by1], c1, rotation),
|
|
1112
|
1195
|
vec.rotWith([ax1, ay1], c0, rotation)
|
|
|
@@ -1120,9 +1203,7 @@ export function getTransformedBoundingBox(
|
|
1120
|
1203
|
)
|
|
1121
|
1204
|
break
|
|
1122
|
1205
|
}
|
|
1123
|
|
- case TransformCorner.BottomRight:
|
|
1124
|
|
- case TransformEdge.Bottom:
|
|
1125
|
|
- case TransformEdge.Right: {
|
|
|
1206
|
+ case TransformCorner.BottomRight: {
|
|
1126
|
1207
|
cv = vec.sub(
|
|
1127
|
1208
|
vec.rotWith([bx0, by0], c1, rotation),
|
|
1128
|
1209
|
vec.rotWith([ax0, ay0], c0, rotation)
|
|
|
@@ -1136,17 +1217,46 @@ export function getTransformedBoundingBox(
|
|
1136
|
1217
|
)
|
|
1137
|
1218
|
break
|
|
1138
|
1219
|
}
|
|
|
1220
|
+ case TransformEdge.Top: {
|
|
|
1221
|
+ cv = vec.sub(
|
|
|
1222
|
+ vec.rotWith(vec.med([bx0, by1], [bx1, by1]), c1, rotation),
|
|
|
1223
|
+ vec.rotWith(vec.med([ax0, ay1], [ax1, ay1]), c0, rotation)
|
|
|
1224
|
+ )
|
|
|
1225
|
+ break
|
|
|
1226
|
+ }
|
|
|
1227
|
+ case TransformEdge.Left: {
|
|
|
1228
|
+ cv = vec.sub(
|
|
|
1229
|
+ vec.rotWith(vec.med([bx1, by0], [bx1, by1]), c1, rotation),
|
|
|
1230
|
+ vec.rotWith(vec.med([ax1, ay0], [ax1, ay1]), c0, rotation)
|
|
|
1231
|
+ )
|
|
|
1232
|
+ break
|
|
|
1233
|
+ }
|
|
|
1234
|
+ case TransformEdge.Bottom: {
|
|
|
1235
|
+ cv = vec.sub(
|
|
|
1236
|
+ vec.rotWith(vec.med([bx0, by0], [bx1, by0]), c1, rotation),
|
|
|
1237
|
+ vec.rotWith(vec.med([ax0, ay0], [ax1, ay0]), c0, rotation)
|
|
|
1238
|
+ )
|
|
|
1239
|
+ break
|
|
|
1240
|
+ }
|
|
|
1241
|
+ case TransformEdge.Right: {
|
|
|
1242
|
+ cv = vec.sub(
|
|
|
1243
|
+ vec.rotWith(vec.med([bx0, by0], [bx0, by1]), c1, rotation),
|
|
|
1244
|
+ vec.rotWith(vec.med([ax0, ay0], [ax0, ay1]), c0, rotation)
|
|
|
1245
|
+ )
|
|
|
1246
|
+ break
|
|
|
1247
|
+ }
|
|
1139
|
1248
|
}
|
|
1140
|
1249
|
|
|
1141
|
1250
|
;[bx0, by0] = vec.sub([bx0, by0], cv)
|
|
1142
|
1251
|
;[bx1, by1] = vec.sub([bx1, by1], cv)
|
|
1143
|
1252
|
}
|
|
1144
|
1253
|
|
|
1145
|
|
- // If the axes are flipped (e.g. if the right edge has been dragged
|
|
1146
|
|
- // left past the initial left edge) then swap points on that axis.
|
|
|
1254
|
+ /*
|
|
|
1255
|
+ 4. Flips
|
|
1147
|
1256
|
|
|
1148
|
|
- let scaleX = (bx1 - bx0) / (ax1 - ax0)
|
|
1149
|
|
- let scaleY = (by1 - by0) / (ay1 - ay0)
|
|
|
1257
|
+ If the axes are flipped (e.g. if the right edge has been dragged
|
|
|
1258
|
+ left past the initial left edge) then swap points on that axis.
|
|
|
1259
|
+ */
|
|
1150
|
1260
|
|
|
1151
|
1261
|
if (bx1 < bx0) {
|
|
1152
|
1262
|
;[bx1, bx0] = [bx0, bx1]
|