完成尺子基本功能
This commit is contained in:
parent
e66fa712b1
commit
c391b7fb76
@ -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",
|
||||
|
||||
29
src/App.vue
29
src/App.vue
@ -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>
|
||||
|
||||
@ -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>
|
||||
171
src/components/dsw-ruler/index.vue
Normal file
171
src/components/dsw-ruler/index.vue
Normal 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
|
||||
}, // 尺子方位,0为水平,1为垂直
|
||||
},
|
||||
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
22
src/components/index.js
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user