完成尺子基本功能

This commit is contained in:
ivo 2022-05-21 14:09:04 +08:00
parent e66fa712b1
commit c391b7fb76
5 changed files with 221 additions and 66 deletions

View File

@ -1,11 +1,14 @@
{
"name": "dsw-ruler",
"version": "0.1.0",
"private": true,
"main": "dist/ruler.dsw.min.js",
"private": false,
"jsx": "preserve",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"lib": "vue-cli-service build --target lib ./src/components/index.js"
},
"dependencies": {
"core-js": "^3.8.3",

View File

@ -1,28 +1,45 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<DswRuler class="horizontal" :minNum="-107" :maxNum="1500" @move="callback" @click="callback"></DswRuler>
<!-- <DswRuler class="vertical" :orientation="1" :minNum="-107" :maxNum="150"></DswRuler> -->
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import DswRuler from "./components/dsw-ruler/index.vue";
export default {
name: 'App',
components: {
HelloWorld
DswRuler
},
methods: {
callback(val) {
console.log(val);
}
}
}
</script>
<style>
#app {
/* #app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
} */
.horizontal {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.vertical {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 20px;
}
</style>

View File

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,171 @@
<template>
<div>
<canvas
id="ruler"
:style="{'width': '100%', 'height': '100%', 'position':position}"
></canvas>
</div>
</template>
<script>
export default {
name: 'DswRuler',
components: {},
props: {
minNum: {
type: Number,
default: 100
},
// position: {
// type: String,
// default: 'relative',
// validator: function(val) {
// return ['absolute', 'fixed', 'relative', 'static', 'inherit'].indexOf(val) !== -1
// }
// }, //
maxNum: {
type: Number,
default: 20
},
orientation: {
type: Number,
default: 0
}, // 01
},
data() {
return {
windowWidth: 0,
windowHeight: 0,
unit: 10,
scale: 1,
}
},
mounted() {
let canvas = document.getElementById('ruler');
canvas.addEventListener('mousemove', this.dottedLineMove, true)
canvas.addEventListener('click', this.dottedLineMove, true)
this.init();
},
methods: {
init() {
this.windowHeight = this.height
// const style = window.getComputedStyle(this.$el.parentNode,null)
// this.windowWidth = parseInt(style.getPropertyValue('width'), 10)
console.log(this.windowWidth);
console.log(this.windowHeight);
let canvas = document.getElementById('ruler');
if (this.orientation) {
this.windowWidth = canvas.getBoundingClientRect().height;
console.log('windowWidth', this.windowWidth);
canvas.height = this.windowWidth;
canvas.width = 20;
} else {
this.windowWidth = canvas.getBoundingClientRect().width;
console.log(this.windowWidth);
canvas.width = this.windowWidth;
canvas.height = 20;
}
this.scale = this.windowWidth / (this.maxNum - this.minNum);
this.drawGrid()
},
drawGrid() {
console.log('draw');
let canvas = document.getElementById('ruler');
if (!canvas.getContext) return;
//
let maxPixel = 0
if (this.orientation) {
maxPixel = canvas.getBoundingClientRect().height;
} else {
maxPixel = canvas.getBoundingClientRect().width;
}
// console.log('maxPixel', maxPixel);
let height = 20
let rulerLength = this.maxNum - this.minNum;
let unitSize = maxPixel / rulerLength
console.log(this.maxNum - this.minNum);
console.log(unitSize);
let unit = 40
if (unitSize < 0.25) {
unit = 40
} else if (unitSize < 0.5) {
unit = 20
} else if (unitSize < 1) {
unit = 10
} else if (unitSize < 2) {
unit = 5
} else {
unit = 2
}
console.log(unit);
let ctx = canvas.getContext("2d");
ctx.fillStyle = "#ACACAC";
for (let i = this.minNum; i < this.maxNum; i++) {
if (i % unit !== 0) continue;
let lineLength = 2
if (i % (unit * 10) !== 0) {
lineLength = 4
} else {
ctx.font="10px sans-serif"
if (this.orientation) {
// todo
// ctx.fillText(i, Math.floor(height / 2), (i - this.minNum + Math.floor(unit / 2)) * this.scale);
ctx.save();
ctx.translate(Math.floor(height), (i - this.minNum + Math.floor(unit / 2)) * this.scale);
ctx.rotate(-90*Math.PI/180);
ctx.fillText(i,4,0);
ctx.restore();
} else {
ctx.fillText(i, (i - this.minNum + Math.floor(unit / 2)) * this.scale, Math.floor(height));
}
}
let x = 0;
let y = 0;
let w = 0;
let h = 0;
if (this.orientation) {
y = (i - this.minNum) * this.scale;
w = Math.floor(height / lineLength)
h = 2
} else {
x = (i - this.minNum) * this.scale;
w = 2
h = Math.floor(height / lineLength)
}
ctx.fillRect(x, y, w, h);
}
ctx.closePath();
},
dottedLineMove(e) {
// let canvas = document.getElementById('ruler').getBoundingClientRect();
let position = 0;
if (this.orientation) {
// console.log(Math.floor((e.pageY) / this.scale) + this.minNum);
position = Math.floor((e.pageY) / this.scale) + this.minNum
} else {
// console.log(Math.floor((e.pageX) / this.scale) + this.minNum);
position = Math.floor((e.pageX) / this.scale) + this.minNum
}
this.$emit('move', position)
}
}
}
</script>
<style scoped>
</style>

22
src/components/index.js Normal file
View File

@ -0,0 +1,22 @@
// 整个包的入口
// 定义 install 方法,接受 Vue 作为参数,如果使用 use 注册插件,则所有组件都将被注册
import DswRuler from '../components/dsw-ruler/index.vue'
const components = [
DswRuler
]
const install = function (Vue) {
// 全局注册所有组件
components.forEach(item => {
Vue.component(item.name, item)
})
}
// 判断是否是以文件方式或者CDN方式如果是则不用调用 Vue.use()。在 CommonJS 中应始终使用 Vue.use()
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default install