????? Why is the uploaded image so wide? The width attribute in the IMG tag is still covered with widescreen
One, foreword
When typing values, you can use a drag ruler instead of a keyboard.
This isn’t the first time we’ve had this requirement, it’s something we wanted to do in the first version of our app. Of course, WHEN I first received this task, I refused to do it. You couldn’t ask me to do it, so I did it right away. First, I had to do some research, because I didn’t want to spend so much time and cost to develop this component and add some special effects.
Sliding over the edge can also duang bounce back, but in fact, it is not as convenient as direct keyboard input numbers, so the leadership will scold me; After some research and time evaluation, I finally chose another plan:
He wrote a set of digital keyboard, much simpler than the scale, also do not consume performance, with very convenient.
Why not use a built-in keyboard? Needless to say, we all know how gross it is to have a keyboard built into a mobile browser call system. However, with the second version of the app, the scale is out again and the product says: “If you cut demand, cut me first!” .
It is true, however, that the second version has more complex scenarios, and that the selected values need to be limited in scope, and the size of the range varies with a number of conditions, so the only way for users to intuitively and quickly enter the correct values is the scale.
Then, after two minutes of careful consideration, I finally took down the task.
Second, the development of
First of all, let’s see what the characteristics of the scale are.
- Can slide;
- Output values according to sliding distance;
- If you slip too far, it bounces back.
It seems that we can develop based on the Scrollview component provided by UNI-app, which has the following properties that are just right for our scale features:
The property name | type | The default value | instructions |
---|---|---|---|
scroll-x | Boolean | false | Allow horizontal scrolling |
scroll-left | Number/String | Sets the horizontal scroll bar position | |
scroll-with-animation | Boolean | false | Use animated transitions when setting the scrollbar position |
@scroll | EventHandle | Detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} |
And then step two, we need to calculate the scale. By default, each scale is 10 pixels.
const GUTTER = 10;
Copy the code
And then we start to calculate how many scales we need, in fact, very simple, is how many scales you need, you pass in a maximum or a minimum, and then subtract the minimum from the maximum, is the number of scales;
There is an interaction problem, because the scale selection mark is placed in the middle of the screen, so the scale boundary needs to display extra scale to fill the screen, so the editor decided to generate an extra scale equivalent to twice the width of the screen;
// The number of extra ticks
const extraGridCount = Math.ceil(window.innerWidth / GUTTER);
// Generates a graduated array
this.gridList = Array.from(Array(this.gridMax - this.gridMin + extraGridCount * 2)).map((_, i) = > {
const num = i + this.gridMin - extraGridCount;
const displayNum = this.decimal === 1 ? num / 10 : num;
return {
num,
displayNum,
isLongGrid: num % GUTTER === 0.showText: num % GUTTER === 0 && num >= this.gridMin && num <= this.gridMax
}
});
Copy the code
Each element in the scale array is a scale object, containing the following properties:
- Scale numerical
- The value displayed on the scale (the value may differ from the actual value and is used to extend the decimal)
- Is it a long scale (because the scale has a long scale every 10)
- Whether to display the value of the scale (only the long scale and the effective scale will display the value)
Array generation, you can render the entire scale according to the array;
<u-row v-if="show" class="grid-wrapper" align="top">
<view
class="grid-item"
:class="{'long': item.isLongGrid}"
v-for="(item, i) in gridList"
:key="i"
:style="item.showText ? { ...gridItemStyle, height: '40px' } : gridItemStyle"
>
<text
class="grid-num"
v-if="item.showText"
>{{item.displayNum}}</text>
</view>
</u-row>
Copy the code
After rendering, you can use some algorithms to calculate the initial position of the scale. Then through scroll event, calculate the value in the process of scale sliding;
scroll(e){
const scrollLeft = e.detail.scrollLeft;
let value = Math.floor((scrollLeft - this.offsetScroll + this.gridMin * GUTTER) / GUTTER);
if(value < this.gridMin){
value = this.gridMin;
}else if(value > this.gridMax){
value = this.gridMax;
}}
Copy the code
OffsetScroll is the redundant part of the scale, which needs to be subtracted, and it needs to determine whether it is less than the minimum or greater than the maximum; Next is the scale rebound, when the slide exceeds the maximum or minimum value, need to rebound, visually consistent with the calculated value; It’s really just at the end of the slide whether the scale should go back to the edge or not, and the scroll view on the animation has done that for us;
adjustScrollPosition(){
/** Adjust the scroll position after the scroll ends */
if(this.actualScrollLeft < this.offsetScroll){
this.scrollLeft = this.offsetScroll + (Math.random() / 100);
} else if(this.actualScrollLeft > (this.gridMax - this.gridMin) * GUTTER + this.offsetScroll){
this.scrollLeft = (this.gridMax - this.gridMin) * GUTTER +
this.offsetScroll + (Math.random() / 100);
} else if(Math.floor(this.actualScrollLeft - this.offsetScroll) % GUTTER ! = =0) {const dryScrollLeft = this.actualScrollLeft - this.offsetScroll;
this.scrollLeft = dryScrollLeft - dryScrollLeft % GUTTER + this.offsetScroll; }}Copy the code
At this point, a scale assembly is almost complete. Of course, there are still many details to be worked out, such as:
- What if you need to support decimal places;
- Is there a performance problem if there are too many scales;
- And so on…
These problems by everyone to think about perfect it, hee hee!