UNPKG

5.22 kBJavaScriptView Raw
1'use strict'
2
3var Region = require('region')
4
5/**
6 *
7 * This method is trying to align the sourceRegion to the targetRegion, given the alignment positions
8 * and the offsets. It only modifies the sourceRegion
9 *
10 * This is all well and easy, but if there is a constrainTo region, the algorithm has to take it into account.
11 * In this case, it works as follows.
12 *
13 * * start with the first alignment position. Aligns the region, adds the offset and then check for the constraint.
14 * * if the constraint condition is ok, return the position.
15 * * otherwise, remember the intersection area, if the regions are intersecting.
16 * * then go to the next specified align position, and so on, computing the maximum intersection area.
17 *
18 * If no alignment fits the constrainRegion, the sourceRegion will be resized to match it,
19 * using the position with the maximum intersection area.
20 *
21 * Since we have computed the index of the position with the max intersection area, take that position,
22 * and align the sourceRegion accordingly. Then resize the sourceRegion to the intersection, and reposition
23 * it again, since resizing it might have destroyed the alignment.
24 *
25 * Return the position.
26 *
27 * @param {Region} sourceRegion
28 * @param {Region} targetRegion
29 * @param {String[]} positions
30 * @param {Object} config
31 * @param {Array} config.offset
32 * @param {Region} config.constrain
33 * @param {Boolean/Object} config.sync
34 *
35 * @return {String/Undefined} the chosen position for the alignment, or undefined if no position found
36 */
37function ALIGN_TO_NORMALIZED(sourceRegion, targetRegion, positions, config){
38
39 targetRegion = Region.from(targetRegion)
40
41 config = config || {}
42
43 var constrainTo = config.constrain,
44 syncOption = config.sync,
45 offsets = config.offset || [],
46 syncWidth = false,
47 syncHeight = false,
48 sourceClone = sourceRegion.clone()
49
50 /*
51 * Prepare the method arguments: positions, offsets, constrain and sync options
52 */
53 if (!Array.isArray(positions)){
54 positions = positions? [positions]: []
55 }
56
57 if (!Array.isArray(offsets)){
58 offsets = offsets? [offsets]: []
59 }
60
61 if (constrainTo){
62 constrainTo = constrainTo === true?
63 Region.getDocRegion():
64 constrainTo.getRegion()
65 }
66
67 if (syncOption){
68
69 if (syncOption.size){
70 syncWidth = true
71 syncHeight = true
72 } else {
73 syncWidth = syncOption === true?
74 true:
75 syncOption.width || false
76
77 syncHeight = syncOption === true?
78 true:
79 syncOption.height || false
80 }
81 }
82
83 if (syncWidth){
84 sourceClone.setWidth(targetRegion.getWidth())
85 }
86 if (syncHeight){
87 sourceClone.setHeight(targetRegion.getHeight())
88
89 }
90
91 var offset,
92 i = 0,
93 len = positions.length,
94 pos,
95 intersection,
96 itArea,
97 maxArea = -1,
98 maxAreaIndex = -1
99
100 for (; i < len; i++){
101 pos = positions[i]
102 offset = offsets[i]
103
104 sourceClone.alignToRegion(targetRegion, pos)
105
106 if (offset){
107 if (!Array.isArray(offset)){
108 offset = offsets[i] = [offset.x || offset.left, offset.y || offset.top]
109 }
110
111 sourceClone.shift({
112 left: offset[0],
113 top : offset[1]
114 })
115 }
116
117 //the source region is already aligned in the correct position
118
119 if (constrainTo){
120 //if we have a constrain region, test for the constrain
121 intersection = sourceClone.getIntersection(constrainTo)
122
123 if ( intersection && intersection.equals(sourceClone) ) {
124 //constrain respected, so return (the aligned position)
125
126 sourceRegion.set(sourceClone)
127 return pos
128 } else {
129
130 //the constrain was not respected, so continue trying
131 if (intersection && ((itArea = intersection.getArea()) > maxArea)){
132 maxArea = itArea
133 maxAreaIndex = i
134 }
135 }
136
137 } else {
138 sourceRegion.set(sourceClone)
139 return pos
140 }
141 }
142
143 //no alignment respected the constraints
144 if (~maxAreaIndex){
145 pos = positions[maxAreaIndex]
146 offset = offsets[maxAreaIndex]
147
148 sourceClone.alignToRegion(targetRegion, pos)
149
150 if (offset){
151 sourceClone.shift({
152 left: offset[0],
153 top : offset[1]
154 })
155 }
156
157 //we are sure an intersection exists, because of the way the maxAreaIndex was computed
158 intersection = sourceClone.getIntersection(constrainTo)
159
160 sourceClone.setRegion(intersection)
161 sourceClone.alignToRegion(targetRegion, pos)
162
163 if (offset){
164 sourceClone.shift({
165 left: offset[0],
166 top : offset[1]
167 })
168 }
169
170 sourceRegion.set(sourceClone)
171
172 return pos
173 }
174
175}
176
177module.exports = ALIGN_TO_NORMALIZED
\No newline at end of file