Skip to content
This repository was archived by the owner on Feb 21, 2023. It is now read-only.

Commit

Permalink
add Avatar, BackToHead, MessageBox, Tag
Browse files Browse the repository at this point in the history
  • Loading branch information
hc-tec committed Jun 5, 2020
1 parent 3f8b560 commit 7796d19
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 14 deletions.
5 changes: 5 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
<style>
html,body {
scroll-behavior: smooth;
}
</style>
</head>
<body>
<noscript>
Expand Down
Binary file added public/克拉默法则.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions src/components/neumorphic/avatar/avatar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<template>
<span class="neumorphic-avatar" :style="neumorphicAvatarContentStyle">
<img
:src="src"
:style="neumorphicAvatarStyle" >
</span>
</template>
<script lang='ts'>
import { Component, Vue, Prop } from 'vue-property-decorator'
import { ShadowType, AvatarFillType } from '../utils/config/neumorphic-type'
@Component
export default class Avatar extends Vue {
@Prop({type: String})
src!: string;
@Prop({type: Boolean, default: false})
circle!: boolean;
@Prop({type: String, default: 'normal'})
shadow!: ShadowType;
@Prop({type: Number, default: 100})
size!: number;
@Prop({type: String, default: 'fill'})
fit!: AvatarFillType;
getShadow(type: ShadowType) {
const shadowMap = {
'normal': `0px 0px 2px #5f5f5f,
0px 0px 0px 5px #ecf0f3,
8px 8px 15px #a7aaaf,
-8px -8px 15px #ffffff`,
'light': `0.3rem 0.3rem 0.6rem hsla(215, 46%, calc(93% - 15%), 0.8),
calc(-1 * 0.3rem) calc(-1 * 0.3rem) 0.6rem hsla(215, 46%, calc(93% + 15%), 0.8)`
}
return shadowMap[type];
}
neumorphicAvatarContentStyle: Record<string, string> = {
'width': `${this.size}px`,
'height': `${this.size}px`,
'border-radius': this.circle ? '50%' : '.5rem',
'box-shadow': this.getShadow(this.shadow)
}
neumorphicAvatarStyle: Record<string, string> = {
'object-fit': this.fit
}
}
</script>
<style scoped>
.neumorphic-avatar {
box-shadow: var(--avatar-shadow);
background-color: var(--primary-bgcolor);
display: inline-block;
box-sizing: border-box;
text-align: center;
overflow: hidden;
}
.neumorphic-avatar > img {
height: 100%;
}
</style>
73 changes: 73 additions & 0 deletions src/components/neumorphic/back-to-head/back-to-head.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<span
ref="neumorphicBackToHead"
class="neumorphic-back-to-head-wrapper"
:style="neumorphicBackToHeadStyle">
<neumorphic-button
class="neumorphic-back-to-head"
@click="backToHead">
<slot></slot>
</neumorphic-button>
</span>
</template>
<script lang='ts'>
import { Component, Vue, Prop } from 'vue-property-decorator'
import neumorphicButton from '../button/button.vue';
@Component({
components: {
'neumorphic-button': neumorphicButton
}
})
export default class BackToHead extends Vue {
@Prop({type: Number, default: 50})
right!: number;
@Prop({type: Number, default: 50})
bottom!: number;
@Prop({type: Number, default: 200})
height!: Number;
neumorphicBackToHeadStyle: Record<string, string> = {
'right': `${this.right}px`,
'bottom': `${this.bottom}px`
}
backToHead() {
document.body.scrollIntoView();
}
mounted(){
let lastScrollPosition = window.pageYOffset;
let button = this.$refs.neumorphicBackToHead as any;
window.addEventListener("scroll",() => {
const watchButtonPos = () => {
let currentScrollPosition = window.pageYOffset;
if (currentScrollPosition < this.height){
button.style.opacity = '0';
button.style.transform = 'translateY(100px)';
} else {
button.style.opacity = '1';
button.style.transform = 'translateY(0)';
}
lastScrollPosition = currentScrollPosition;
}
setTimeout(() => {
watchButtonPos()
}, 200);
});
}
}
</script>
<style scoped>
.neumorphic-back-to-head-wrapper {
position: fixed;
transform: translateY(100px);
transition: opacity .3s, transform .3s ;
}
.neumorphic-back-to-head {
padding: 15px;
}
</style>
1 change: 1 addition & 0 deletions src/components/neumorphic/button/button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Component, Vue, Prop, Emit } from 'vue-property-decorator'
@Component
export default class NeumorphicBtn extends Vue {
@Prop({ type: Boolean, default: false }) private circle!: boolean;
neumorphicButtonClass: Record<string, boolean> = {
'neumorphic-btn': true,
'neumorphic-btn-circle': this.circle
Expand Down
38 changes: 38 additions & 0 deletions src/components/neumorphic/messageBox/messageBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { MessageBoxConfig } from './messageBoxConfig';

export class MessageBox {
public topList: number[] = [0];
public setMsg(config: MessageBoxConfig): void {
// topList 用于储存每个 messageBox 的 top 属性,为局部的"全局变量",必须
this.generateMessageBox(config);
}
private generateMessageBox(config: MessageBoxConfig): void {
const messageBox = this.generateElement('div', 'neumorphic-messagebox');
const top = this.topList[this.topList.length - 1] + 55;
this.topList.push(top);
messageBox.style.top = `${top}px`;
const message = this.generateElement('p', 'neumorphic-messagebox-text');
message.appendChild(document.createTextNode(config.message));
messageBox.appendChild(message);
const body = document.body;
body.appendChild(messageBox);
setTimeout(() => {
messageBox.style.transform = 'translate(-50%, 0)';
}, 100);
setTimeout(() => {
messageBox.style.transform = 'translate(-50%, -100px)';
}, config.styleTimeout);
setTimeout(() => {
body.removeChild(messageBox);
this.topList.pop();
}, config.removeTimeout);
}

private generateElement(element: string, className: string): HTMLElement {
const ele = document.createElement(element);
ele.className = className;
return ele;
}

}
export default new MessageBox();
21 changes: 21 additions & 0 deletions src/components/neumorphic/messageBox/messageBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<div class="neumorphic-messagebox">
<p class="neumorphic-messagebox-text">
<slot></slot>
</p>
</div>
</template>
<script lang='ts'>
import { Component, Vue, Prop } from 'vue-property-decorator';
import { MessageBox } from './messageBox';
// @Component
export default class NeuMessageBox extends MessageBox {
}
</script>
<style scoped>
</style>
6 changes: 6 additions & 0 deletions src/components/neumorphic/messageBox/messageBoxConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface MessageBoxConfig {
message: string;
styleTimeout: number;
removeTimeout: number;
}

77 changes: 77 additions & 0 deletions src/components/neumorphic/tag/tag.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<span class="neumorphic-tag">
<span v-if="prefixIcon" class="neumorphic-tag-icon neumorphic-tag-prefix-icon">
<i :class="prefixIcon"></i>
</span>
<p class="neumorphic-tag-text" ref="neumorphicTagText">
<slot></slot>
</p>
<span
class="neumorphic-tag-icon neumorphic-tag-close"
v-if="closable"
@click="handleClose">
</span>
</span>
</template>
<script lang='ts'>
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component
export default class Tag extends Vue {
@Prop({default: ''})
prefixIcon?: string;
@Prop({default: false})
closable?: boolean;
handleClose() {
// 点击关闭按钮触发的事件
const tagText = (this.$refs.neumorphicTagText as HTMLParagraphElement).innerHTML
this.$emit('close', tagText);
}
}
</script>
<style scoped>
.neumorphic-tag {
min-width: 5rem;
min-height: 2rem;
border-radius: var(--small-radius);
box-shadow: var(--shadow);
display: inline-flex;
justify-content: unset;
align-items: center;
position: relative;
margin-right: 10px;
}
.neumorphic-tag-icon {
width: 1rem;
height: 1rem;
border-radius: var(--primary-radius);
display: flex;
justify-content: center;
align-items: center;
font-size: var(--primary-font-size);
color: var(--second-color);
margin: 0 0 0 .2rem;
}
.neumorphic-tag-prefix-icon {
left: 0;
}
.neumorphic-tag-close {
cursor: pointer;
right: .5rem;
color: var(--primary-color);
transition: color .3s;
position: absolute;
}
.neumorphic-tag-close:hover {
color: var(--second-color);
}
.neumorphic-tag-text {
font-size: var(--primary-font-size);
color: var(--primary-color);
margin: 0 2rem 0 .5rem;
}
</style>
7 changes: 7 additions & 0 deletions src/components/neumorphic/utils/config/neumorphic-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


export type ShadowType = 'normal' | 'light';

export type AvatarFillType = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';


27 changes: 27 additions & 0 deletions src/components/neumorphic/utils/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
/* 文字阴影 */
--text-shadow: 1px 1px 0 #FFF;

/* 特殊处理:头像阴影 */
--avatar-shadow: 0px 0px 2px #5f5f5f,
0px 0px 0px 5px #ecf0f3,
8px 8px 15px #a7aaaf,
-8px -8px 15px #ffffff;

/* 主要文字大小 */
--primary-font-size: .9rem;
--bigger-font-size: 1.1rem;
Expand All @@ -73,4 +79,25 @@

/* 特殊处理:分割线弧度 */
--divider-radius: .5rem;
}


.neumorphic-messagebox {
width: 20rem;
height: 3rem;
border-radius: var(--small-radius);
box-shadow: var(--shadow);
display: flex;
justify-content: unset;
align-items: center;
position: fixed;
left: 50%;
top: 10px;
transform: translate(-50%, -100px);
transition: all .5s;
}
.neumorphic-messagebox-text {
font-size: var(--primary-font-size);
color: var(--primary-color);
margin-left: 2rem;
}
Loading

0 comments on commit 7796d19

Please sign in to comment.