mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-02-07 10:10:19 +08:00
添加样式预览
This commit is contained in:
parent
e0df7bc3d6
commit
fe598369b7
@ -1,222 +1,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
import {mergeConfig} from '@/utils'
|
||||
|
||||
const DEFAULT_CSS = `@import url("https://fonts.googleapis.com/css?family=Changa%20One");
|
||||
@import url("https://fonts.googleapis.com/css?family=Imprima");
|
||||
/* @import url("https://fonts.lug.ustc.edu.cn/css?family=Changa%20One"); */
|
||||
/* @import url("https://fonts.lug.ustc.edu.cn/css?family=Imprima"); */
|
||||
|
||||
/* Background colors*/
|
||||
body {
|
||||
overflow: hidden;
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
/* Transparent background. */
|
||||
yt-live-chat-renderer {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-text-message-renderer[is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="owner"],
|
||||
yt-live-chat-text-message-renderer[author-type="owner"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"],
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="member"],
|
||||
yt-live-chat-text-message-renderer[author-type="member"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-author-chip #author-name {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* Outlines */
|
||||
yt-live-chat-renderer * {
|
||||
text-shadow: -2px -2px #000000,-2px -1px #000000,-2px 0px #000000,-2px 1px #000000,-2px 2px #000000,-1px -2px #000000,-1px -1px #000000,-1px 0px #000000,-1px 1px #000000,-1px 2px #000000,0px -2px #000000,0px -1px #000000,0px 0px #000000,0px 1px #000000,0px 2px #000000,1px -2px #000000,1px -1px #000000,1px 0px #000000,1px 1px #000000,1px 2px #000000,2px -2px #000000,2px -1px #000000,2px 0px #000000,2px 1px #000000,2px 2px #000000;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #content,
|
||||
yt-live-chat-legacy-paid-message-renderer #content {
|
||||
overflow: initial !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar. */
|
||||
yt-live-chat-item-list-renderer #items{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
yt-live-chat-item-list-renderer #item-scroller{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* Hide header and input. */
|
||||
yt-live-chat-header-renderer,
|
||||
yt-live-chat-message-input-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Reduce side padding. */
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #header {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
/* Avatars. */
|
||||
yt-live-chat-text-message-renderer #author-photo,
|
||||
yt-live-chat-paid-message-renderer #author-photo,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo {
|
||||
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
border-radius: 24px !important;
|
||||
margin-right: 6px !important;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* Hide badges. */
|
||||
yt-live-chat-text-message-renderer #author-badges {
|
||||
display: none !important;
|
||||
vertical-align: text-top !important;
|
||||
}
|
||||
|
||||
/* Timestamps. */
|
||||
yt-live-chat-text-message-renderer #timestamp {
|
||||
|
||||
color: #999999 !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 16px !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
/* Badges. */
|
||||
yt-live-chat-text-message-renderer #author-name[type="owner"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="owner"] {
|
||||
color: #ffd600 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="moderator"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="moderator"] {
|
||||
color: #5e84f1 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="member"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="member"] {
|
||||
color: #0f9d58 !important;
|
||||
}
|
||||
|
||||
/* Channel names. */
|
||||
yt-live-chat-text-message-renderer #author-name {
|
||||
color: #cccccc !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name::after {
|
||||
content: ":";
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
/* Messages. */
|
||||
yt-live-chat-text-message-renderer #message,
|
||||
yt-live-chat-text-message-renderer #message * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
|
||||
/* SuperChat/Fan Funding Messages. */
|
||||
yt-live-chat-paid-message-renderer #author-name,
|
||||
yt-live-chat-paid-message-renderer #author-name *,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #purchase-amount,
|
||||
yt-live-chat-paid-message-renderer #purchase-amount *,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #content,
|
||||
yt-live-chat-paid-message-renderer #content * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer {
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
background-color: #0f9d58 !important;
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer a,
|
||||
yt-live-chat-legacy-paid-message-renderer a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[is-deleted],
|
||||
yt-live-chat-legacy-paid-message-renderer[is-deleted] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-ticker-renderer {
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
yt-live-chat-ticker-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-ticker-paid-message-item-renderer,
|
||||
yt-live-chat-ticker-paid-message-item-renderer *,
|
||||
yt-live-chat-ticker-sponsor-item-renderer,
|
||||
yt-live-chat-ticker-sponsor-item-renderer * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
}
|
||||
|
||||
yt-live-chat-mode-change-message-renderer,
|
||||
yt-live-chat-viewer-engagement-message-renderer,
|
||||
yt-live-chat-restricted-participation-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
`
|
||||
import stylegen from '@/views/StyleGenerator/stylegen'
|
||||
|
||||
export const DEFAULT_CONFIG = {
|
||||
minGiftPrice: 6.911, // $1
|
||||
@ -229,7 +14,7 @@ export const DEFAULT_CONFIG = {
|
||||
blockKeywords: '',
|
||||
blockUsers: '',
|
||||
|
||||
css: DEFAULT_CSS
|
||||
css: stylegen.getStyle(stylegen.DEFAULT_CONFIG)
|
||||
}
|
||||
|
||||
export function setLocalConfig (config) {
|
||||
|
@ -71,6 +71,8 @@ yt-live-chat-text-message-renderer>#content>.el-badge {
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer>#content>.el-badge .el-badge__content {
|
||||
font-size: 12px !important;
|
||||
line-height: 18px !important;
|
||||
text-shadow: none !important;
|
||||
font-family: sans-serif !important;
|
||||
background-color: var(--repeated-mark-color) !important;
|
@ -43,164 +43,41 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/api/config'
|
||||
import TextMessage from './TextMessage.vue'
|
||||
import LegacyPaidMessage from './LegacyPaidMessage.vue'
|
||||
import PaidMessage from './PaidMessage.vue'
|
||||
|
||||
const COMMAND_JOIN_ROOM = 0
|
||||
const COMMAND_ADD_TEXT = 1
|
||||
const COMMAND_ADD_GIFT = 2
|
||||
const COMMAND_ADD_VIP = 3
|
||||
|
||||
export default {
|
||||
name: 'Room',
|
||||
name: 'ChatRenderer',
|
||||
components: {
|
||||
TextMessage,
|
||||
LegacyPaidMessage,
|
||||
PaidMessage
|
||||
},
|
||||
props: {
|
||||
messages: Array,
|
||||
css: String
|
||||
},
|
||||
data() {
|
||||
let cfg = {...config.DEFAULT_CONFIG}
|
||||
cfg.blockKeywords = cfg.blockKeywords.split('\n').filter(val => val)
|
||||
cfg.blockUsers = cfg.blockUsers.split('\n').filter(val => val)
|
||||
let styleElement = document.createElement('style')
|
||||
styleElement.innerText = cfg.css
|
||||
document.head.appendChild(styleElement)
|
||||
return {
|
||||
config: cfg,
|
||||
styleElement,
|
||||
websocket: null,
|
||||
messages: [],
|
||||
nextId: 0
|
||||
styleElement
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
// 开发时使用localhost:80
|
||||
const url = process.env.NODE_ENV === 'development' ? 'ws://localhost/chat' : `ws://${window.location.host}/chat`
|
||||
this.websocket = new WebSocket(url)
|
||||
this.websocket.onopen = this.onWsOpen.bind(this)
|
||||
this.websocket.onmessage = this.onWsMessage.bind(this)
|
||||
|
||||
if (this.$route.query.config_id) {
|
||||
try {
|
||||
let cfg = await config.getRemoteConfig(this.$route.query.config_id)
|
||||
cfg.blockKeywords = cfg.blockKeywords.split('\n').filter(val => val)
|
||||
cfg.blockUsers = cfg.blockUsers.split('\n').filter(val => val)
|
||||
this.styleElement.innerText = cfg.css
|
||||
this.config = cfg
|
||||
} catch (e) {
|
||||
this.$message.error('获取配置失败:' + e)
|
||||
}
|
||||
}
|
||||
mounted() {
|
||||
this.styleElement.innerText = this.css
|
||||
this.$refs.scroller.scrollTo(0, this.$refs.scroller.scrollHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.head.removeChild(this.styleElement)
|
||||
this.websocket.close()
|
||||
},
|
||||
updated() {
|
||||
this.$refs.scroller.scrollTo(0, this.$refs.scroller.scrollHeight)
|
||||
},
|
||||
methods: {
|
||||
onWsOpen() {
|
||||
this.websocket.send(JSON.stringify({
|
||||
cmd: COMMAND_JOIN_ROOM,
|
||||
data: {
|
||||
roomId: parseInt(this.$route.params.roomId)
|
||||
}
|
||||
}))
|
||||
},
|
||||
onWsMessage(event) {
|
||||
let {cmd, data} = JSON.parse(event.data)
|
||||
let message = null
|
||||
let time = data.timestamp ? new Date(data.timestamp * 1000) : new Date()
|
||||
switch(cmd) {
|
||||
case COMMAND_ADD_TEXT:
|
||||
if (!this.filterTextMessage(data) || this.mergeSimilar(data.content)) {
|
||||
break
|
||||
}
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 0, // TextMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: data.authorName,
|
||||
authorType: data.authorType,
|
||||
content: data.content,
|
||||
repeated: 1
|
||||
}
|
||||
break
|
||||
case COMMAND_ADD_GIFT: {
|
||||
let price = data.totalCoin / 1000
|
||||
if (price < this.config.minGiftPrice) // 丢人
|
||||
break
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 2, // PaidMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
authorName: data.authorName,
|
||||
price: price,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
content: `Sent ${data.giftName}x${data.giftNum}`
|
||||
}
|
||||
break
|
||||
}
|
||||
case COMMAND_ADD_VIP:
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 1, // LegacyPaidMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: data.authorName,
|
||||
title: 'NEW MEMBER!',
|
||||
content: `Welcome ${data.authorName}`
|
||||
}
|
||||
break
|
||||
}
|
||||
if (message) {
|
||||
this.messages.push(message)
|
||||
if (this.messages.length > 50) {
|
||||
this.messages.splice(0, this.messages.length - 50)
|
||||
}
|
||||
}
|
||||
},
|
||||
filterTextMessage(data) {
|
||||
if (this.config.blockGiftDanmaku && data.isGiftDanmaku) {
|
||||
return false
|
||||
} else if (this.config.blockLevel > 0 && data.authorLevel < this.config.blockLevel) {
|
||||
return false
|
||||
} else if (this.config.blockNewbie && data.isNewbie) {
|
||||
return false
|
||||
} else if (this.config.blockNotMobileVerified && !data.isMobileVerified) {
|
||||
return false
|
||||
}
|
||||
for (let keyword of this.config.blockKeywords) {
|
||||
if (data.content.indexOf(keyword) !== -1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for (let user of this.config.blockUsers) {
|
||||
if (data.authorName === user) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
mergeSimilar(content) {
|
||||
if (!this.config.mergeSimilarDanmaku) {
|
||||
return false
|
||||
}
|
||||
for (let i = this.messages.length - 1; i >= 0 && i >= this.messages.length - 5; i--) {
|
||||
let message = this.messages[i]
|
||||
if (
|
||||
(message.content.indexOf(content) !== -1 || content.indexOf(message.content) !== -1) // 包含对方
|
||||
&& Math.abs(message.content.length - content.length) < Math.min(message.content.length, content.length) // 长度差比两者长度都小
|
||||
) {
|
||||
message.repeated++
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
watch: {
|
||||
css(val) {
|
||||
this.styleElement.innerText = val
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import App from './App.vue'
|
||||
import Layout from './layout'
|
||||
import Home from './views/Home.vue'
|
||||
import StyleGenerator from './views/StyleGenerator'
|
||||
import Room from './views/Room'
|
||||
import Room from './views/Room.vue'
|
||||
import NotFound from './views/NotFound.vue'
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
|
154
frontend/src/views/Room.vue
Normal file
154
frontend/src/views/Room.vue
Normal file
@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<chat-renderer :messages="messages" :css="config.css"></chat-renderer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/api/config'
|
||||
import ChatRenderer from '@/components/ChatRenderer'
|
||||
|
||||
const COMMAND_JOIN_ROOM = 0
|
||||
const COMMAND_ADD_TEXT = 1
|
||||
const COMMAND_ADD_GIFT = 2
|
||||
const COMMAND_ADD_VIP = 3
|
||||
|
||||
export default {
|
||||
name: 'Room',
|
||||
components: {
|
||||
ChatRenderer
|
||||
},
|
||||
data() {
|
||||
let cfg = {...config.DEFAULT_CONFIG}
|
||||
cfg.blockKeywords = cfg.blockKeywords.split('\n').filter(val => val)
|
||||
cfg.blockUsers = cfg.blockUsers.split('\n').filter(val => val)
|
||||
return {
|
||||
config: cfg,
|
||||
websocket: null,
|
||||
messages: [],
|
||||
nextId: 0
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
// 开发时使用localhost:80
|
||||
const url = process.env.NODE_ENV === 'development' ? 'ws://localhost/chat' : `ws://${window.location.host}/chat`
|
||||
this.websocket = new WebSocket(url)
|
||||
this.websocket.onopen = this.onWsOpen.bind(this)
|
||||
this.websocket.onmessage = this.onWsMessage.bind(this)
|
||||
|
||||
if (this.$route.query.config_id) {
|
||||
try {
|
||||
let cfg = await config.getRemoteConfig(this.$route.query.config_id)
|
||||
cfg.blockKeywords = cfg.blockKeywords.split('\n').filter(val => val)
|
||||
cfg.blockUsers = cfg.blockUsers.split('\n').filter(val => val)
|
||||
this.config = cfg
|
||||
} catch (e) {
|
||||
this.$message.error('获取配置失败:' + e)
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.websocket.close()
|
||||
},
|
||||
methods: {
|
||||
onWsOpen() {
|
||||
this.websocket.send(JSON.stringify({
|
||||
cmd: COMMAND_JOIN_ROOM,
|
||||
data: {
|
||||
roomId: parseInt(this.$route.params.roomId)
|
||||
}
|
||||
}))
|
||||
},
|
||||
onWsMessage(event) {
|
||||
let {cmd, data} = JSON.parse(event.data)
|
||||
let message = null
|
||||
let time = data.timestamp ? new Date(data.timestamp * 1000) : new Date()
|
||||
switch(cmd) {
|
||||
case COMMAND_ADD_TEXT:
|
||||
if (!this.filterTextMessage(data) || this.mergeSimilar(data.content)) {
|
||||
break
|
||||
}
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 0, // TextMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: data.authorName,
|
||||
authorType: data.authorType,
|
||||
content: data.content,
|
||||
repeated: 1
|
||||
}
|
||||
break
|
||||
case COMMAND_ADD_GIFT: {
|
||||
let price = data.totalCoin / 1000
|
||||
if (price < this.config.minGiftPrice) // 丢人
|
||||
break
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 2, // PaidMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
authorName: data.authorName,
|
||||
price: price,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
content: `Sent ${data.giftName}x${data.giftNum}`
|
||||
}
|
||||
break
|
||||
}
|
||||
case COMMAND_ADD_VIP:
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
type: 1, // LegacyPaidMessage
|
||||
avatarUrl: data.avatarUrl,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: data.authorName,
|
||||
title: 'NEW MEMBER!',
|
||||
content: `Welcome ${data.authorName}`
|
||||
}
|
||||
break
|
||||
}
|
||||
if (message) {
|
||||
this.messages.push(message)
|
||||
if (this.messages.length > 50) {
|
||||
this.messages.splice(0, this.messages.length - 50)
|
||||
}
|
||||
}
|
||||
},
|
||||
filterTextMessage(data) {
|
||||
if (this.config.blockGiftDanmaku && data.isGiftDanmaku) {
|
||||
return false
|
||||
} else if (this.config.blockLevel > 0 && data.authorLevel < this.config.blockLevel) {
|
||||
return false
|
||||
} else if (this.config.blockNewbie && data.isNewbie) {
|
||||
return false
|
||||
} else if (this.config.blockNotMobileVerified && !data.isMobileVerified) {
|
||||
return false
|
||||
}
|
||||
for (let keyword of this.config.blockKeywords) {
|
||||
if (data.content.indexOf(keyword) !== -1) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for (let user of this.config.blockUsers) {
|
||||
if (data.authorName === user) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
mergeSimilar(content) {
|
||||
if (!this.config.mergeSimilarDanmaku) {
|
||||
return false
|
||||
}
|
||||
for (let i = this.messages.length - 1; i >= 0 && i >= this.messages.length - 5; i--) {
|
||||
let message = this.messages[i]
|
||||
if (
|
||||
(message.content.indexOf(content) !== -1 || content.indexOf(message.content) !== -1) // 包含对方
|
||||
&& Math.abs(message.content.length - content.length) < Math.min(message.content.length, content.length) // 长度差比两者长度都小
|
||||
) {
|
||||
message.repeated++
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form label-width="150px" size="mini">
|
||||
<h3>描边</h3>
|
||||
@ -132,13 +132,13 @@
|
||||
<el-form-item label="SuperChat内容字体">
|
||||
<el-autocomplete v-model="form.scContentFont" :fetch-suggestions="getFontSuggestions"></el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item label="SuperChat字体尺寸">
|
||||
<el-form-item label="SuperChat内容字体尺寸">
|
||||
<el-input v-model.number="form.scContentFontSize" type="number" min="0"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="SuperChat行高(0为默认)">
|
||||
<el-form-item label="SuperChat内容行高(0为默认)">
|
||||
<el-input v-model.number="form.scContentLineHeight" type="number" min="0"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="SuperChat颜色">
|
||||
<el-form-item label="SuperChat内容颜色">
|
||||
<el-color-picker v-model="form.scContentColor"></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="显示新舰长背景">
|
||||
@ -173,6 +173,9 @@
|
||||
<el-form-item label="反向滑动">
|
||||
<el-switch v-model="form.reverseSlide"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="playAnimation">播放动画</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<h3>结果</h3>
|
||||
<el-form-item label="CSS">
|
||||
@ -185,7 +188,11 @@
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
预览
|
||||
<div id="example-container">
|
||||
<div id="fakebody">
|
||||
<chat-renderer :messages="messages" :css="exampleCss"></chat-renderer>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
@ -195,15 +202,98 @@ import _ from 'lodash'
|
||||
|
||||
import stylegen from './stylegen'
|
||||
import fonts from './fonts'
|
||||
import ChatRenderer from '@/components/ChatRenderer'
|
||||
|
||||
let time = new Date()
|
||||
let textMessageTemplate = {
|
||||
id: 0,
|
||||
type: 0, // TextMessage
|
||||
avatarUrl: 'https://static.hdslb.com/images/member/noface.gif',
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: '',
|
||||
authorType: 0,
|
||||
content: '',
|
||||
repeated: 1
|
||||
}
|
||||
let legacyPaidMessageTemplate = {
|
||||
id: 0,
|
||||
type: 1, // LegacyPaidMessage
|
||||
avatarUrl: 'https://static.hdslb.com/images/member/noface.gif',
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
authorName: '',
|
||||
title: 'NEW MEMBER!',
|
||||
content: ''
|
||||
}
|
||||
let paidMessageTemplate = {
|
||||
id: 0,
|
||||
type: 2, // PaidMessage
|
||||
avatarUrl: 'https://static.hdslb.com/images/member/noface.gif',
|
||||
authorName: '',
|
||||
price: 0,
|
||||
time: `${time.getMinutes()}:${time.getSeconds()}`,
|
||||
content: ''
|
||||
}
|
||||
let nextId = 0
|
||||
const EXAMPLE_MESSAGES = [
|
||||
{
|
||||
...textMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: 'mob路人',
|
||||
content: '8888888888',
|
||||
repeated: 12
|
||||
}, {
|
||||
...textMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: 'member舰长',
|
||||
authorType: 1,
|
||||
content: '草',
|
||||
repeated: 3
|
||||
}, {
|
||||
...textMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: 'admin房管',
|
||||
authorType: 2,
|
||||
content: 'kksk'
|
||||
}, {
|
||||
...legacyPaidMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: 'Paryi',
|
||||
content: 'Welcome Paryi'
|
||||
}, {
|
||||
...paidMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: '石油佬',
|
||||
price: 1245,
|
||||
content: 'Sent 小电视飞船x1'
|
||||
}, {
|
||||
...textMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: 'streamer主播',
|
||||
authorType: 3,
|
||||
content: '感谢石油佬送的小电视'
|
||||
}, {
|
||||
...paidMessageTemplate,
|
||||
id: nextId++,
|
||||
authorName: '臭DD',
|
||||
price: 28,
|
||||
content: 'Sent 礼花x1'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'StyleGenerator',
|
||||
components: {
|
||||
ChatRenderer
|
||||
},
|
||||
data() {
|
||||
let config = stylegen.getLocalConfig()
|
||||
let result = stylegen.getStyle(config)
|
||||
return {
|
||||
FONTS: [...fonts.LOCAL_FONTS, ...fonts.NETWORK_FONTS],
|
||||
form: {...config},
|
||||
result: stylegen.getStyle(config)
|
||||
result,
|
||||
exampleCss: result.replace(/^body\b/gm, '#fakebody'),
|
||||
messages: EXAMPLE_MESSAGES
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -222,6 +312,10 @@ export default {
|
||||
}
|
||||
callback(res)
|
||||
},
|
||||
playAnimation() {
|
||||
this.messages = []
|
||||
this.$nextTick(() => this.messages = EXAMPLE_MESSAGES)
|
||||
},
|
||||
copyResult() {
|
||||
this.$refs.result.select()
|
||||
document.execCommand('Copy')
|
||||
@ -231,10 +325,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
computedResult: _.debounce(function (result) {
|
||||
this.result = result
|
||||
computedResult: _.debounce(function (val) {
|
||||
this.result = val
|
||||
stylegen.setLocalConfig(this.form)
|
||||
}, 500)
|
||||
}, 500),
|
||||
result (val) {
|
||||
this.exampleCss = val.replace(/^body\b/gm, '#fakebody')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -243,4 +340,37 @@ export default {
|
||||
.el-form {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#example-container {
|
||||
position: fixed;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
width: 400px;
|
||||
height: calc(100vh - 110px);
|
||||
|
||||
background-color: #444;
|
||||
background-image:
|
||||
-moz-linear-gradient(45deg, #333 25%, transparent 25%),
|
||||
-moz-linear-gradient(-45deg, #333 25%, transparent 25%),
|
||||
-moz-linear-gradient(45deg, transparent 75%, #333 75%),
|
||||
-moz-linear-gradient(-45deg, transparent 75%, #333 75%);
|
||||
background-image:
|
||||
-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #333), color-stop(.25, transparent)),
|
||||
-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #333), color-stop(.25, transparent)),
|
||||
-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #333)),
|
||||
-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #333));
|
||||
|
||||
-moz-background-size:32px 32px;
|
||||
background-size:32px 32px;
|
||||
-webkit-background-size:32px 32px;
|
||||
|
||||
background-position:0 0, 16px 0, 16px -16px, 0px 16px;
|
||||
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
#fakebody {
|
||||
outline: 1px #999 dashed;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
@ -31,12 +31,12 @@ export const DEFAULT_CONFIG = {
|
||||
timeLineHeight: 0,
|
||||
timeColor: '#999999',
|
||||
|
||||
bgColor: '#000000',
|
||||
bgColor: 'rgba(0, 0, 0, 0)',
|
||||
useBarsInsteadOfBg: false,
|
||||
messageBgColor: '#cccccc',
|
||||
ownerMessageBgColor: '#ffd600',
|
||||
moderatorMessageBgColor: '#5e84f1',
|
||||
memberMessageBgColor: '#0f9d58',
|
||||
messageBgColor: 'rgba(204, 204, 204, 0)',
|
||||
ownerMessageBgColor: 'rgba(255, 214, 0, 0)',
|
||||
moderatorMessageBgColor: 'rgba(94, 132, 241, 0)',
|
||||
memberMessageBgColor: 'rgba(15, 157, 88, 0)',
|
||||
|
||||
firstLineFont: 'Changa One',
|
||||
firstLineFontSize: 20,
|
||||
@ -47,7 +47,7 @@ export const DEFAULT_CONFIG = {
|
||||
secondLineLineHeight: 0,
|
||||
secondLineColor: '#ffffff',
|
||||
scContentFont: 'Imprima',
|
||||
scContentFontSize: 28,
|
||||
scContentFontSize: 18,
|
||||
scContentLineHeight: 0,
|
||||
scContentColor: '#ffffff',
|
||||
showNewMemberBg: true,
|
||||
@ -142,8 +142,11 @@ yt-live-chat-paid-message-renderer #header {
|
||||
|
||||
/* Avatars. */
|
||||
yt-live-chat-text-message-renderer #author-photo,
|
||||
yt-live-chat-text-message-renderer #author-photo img,
|
||||
yt-live-chat-paid-message-renderer #author-photo,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo {
|
||||
yt-live-chat-paid-message-renderer #author-photo img,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo img {
|
||||
${config.showAvatars ? '' : 'display: none !important;'}
|
||||
width: ${config.avatarSize}px !important;
|
||||
height: ${config.avatarSize}px !important;
|
||||
@ -159,7 +162,7 @@ yt-live-chat-text-message-renderer #author-badges {
|
||||
|
||||
/* Timestamps. */
|
||||
yt-live-chat-text-message-renderer #timestamp {
|
||||
${config.showTime ? '' : 'display: none !important;'}
|
||||
display: ${config.showTime ? 'inline' : 'none'} !important;
|
||||
${config.timeColor ? `color: ${config.timeColor} !important;` : ''}
|
||||
font-family: "${config.timeFont}", sans-serif;
|
||||
font-size: ${config.timeFontSize}px !important;
|
||||
|
Loading…
Reference in New Issue
Block a user