preface

Recently, the development of micro channel small program received a nine grid lottery demand, write the process of feeling quite interesting, write components, by the way to record the psychological journey. After consideration before development, it is roughly divided into the following modules: layout, animation and events. The technology stack is UNI-APP + TS + less.

layout

First write the template, render the grid options and raffle button to highlight the active state:

<template>
	<view class="turntable">
		<view
			class="turntable__item"
			:class="[curIdx === idx ? 'turntable__item--active' : null]"
			v-for="(item, idx) in options"
			:key="idx"
		>Index: {{idx}}</view>
		<view class="turntable__raffle" @click="raffle">Lucky draw</view>
	</view>
</template>
Copy the code

Then write less, because of the unique structure of nine grid, I thought of the grid layout, so a sudden operation like tiger:

.turntable {
	width: 630rpx;
	height: 630rpx;
	margin: 24rpx auto 76rpx;
	padding: 21rpx;
	background: rgba(255.255.255.0.3);
	display: grid;
	grid-template-columns: 184rpx 184rpx 184rpx;
	grid-template-rows: 184rpx 184rpx 184rpx;
	grid-row-gap: 18rpx;
	grid-column-gap: 18rpx;

	&__raffle {
		background: #ffda44;
		grid-area: ~"2 / 2";
	}

	&__item {
		background: #fff;
		opacity: 0.3;

		&--active {
			opacity: 1; }}}Copy the code

The grid-area attribute is used to specify the size and location of grid items in the grid layout. For example:

/* Make "item1" start at row 2, column 1, and span 2 rows and 3 columns: */
.item1 {
	grid-area: 2 / 1 / span 2 / span 3;
}
Copy the code

So, I define the first grid in the upper left corner as the starting point, and its coordinate is (1,1). Then, if it jumps clockwise, I will perform operations such as jump right > jump down > jump left > jump up along the border.

import { Component, Prop, Vue, Watch } from "vue-property-decorator";

type Direction = "up" | "down" | "left" | "right";
type Rotation = "clockwise" | "anticlockwise";

const ROW = 3; / / the number of rows
const COL = 3; / / the number of columns
const CLOCKWISE_DIRECTIONS: Direction[] = ["right"."down"."left"."up"]; // Turn clockwise to the path
const ANTICLOCKWISE_DIRECTIONS: Direction[] = ["down"."right"."up"."left"]; // The path of the counterclockwise turn

@Component
export default class extends Vue {
	/** * beat direction, default clockwise */
	@Prop({ default: "clockwise" }) rotation: Rotation = "clockwise";

	/** * Jump path */
	private get directions() {
		return this.rotation === "clockwise"
			? CLOCKWISE_DIRECTIONS
			: ANTICLOCKWISE_DIRECTIONS;
	}

	/** * Prize grid-area value */
	private get gridAreas() {
		let x = 1;
		let y = 1;
		return this.directions.reduce((pre, item) = > {
			switch (item) {
				case "up":
					while (y > 1) {
						pre.push(`${y}/${x}`);
						y--;
					}
					y = y < 1 ? 1 : y;
					break;
				case "down":
					while (y < ROW) {
						pre.push(`${y}/${x}`);
						y++;
					}
					y = y > COL ? COL : y;
					break;
				case "left":
					while (x > 1) {
						pre.push(`${y}/${x}`);
						x--;
					}
					x = x < 1 ? 1 : x;
					break;
				case "right":
					while (x < COL) {
						pre.push(`${y}/${x}`);
						x++;
					}
					x = x > ROW ? ROW : x;
					break;
			}
			return pre;
		}, [] as string[]); }}Copy the code

Add the style attribute to turnTable__item:

<view class="turntable__item" :style="{ gridArea: gridAreas[idx] }" .></view>
Copy the code

At this point, completed the layout of nine grids.

To be continued…

reference

www.jc2182.com/css/css-gri…