在前两篇文章中,我们已经完成了大部分的工作,接下来,我们将编写页面样式以及交互部分。把这个项目完善好。
系列
在线使用地址:qc2168.github.io/article-inf…
页面布局
输入卡片样式
将body标签中设置flex布局,让元素能够居中。并将背景颜色设置为灰色,并在里边给一个容器组件,使用mx-auto功能类,
<body class="bg-gray-300 flex justify-center items-center">
<div id="container" class="container mx-auto flex flex-nowrap">
</div>
</body>
在body标签中创建一个卡片,这里使用了较多的tailwind的样式类,如果你是第一次接触这类框架,你可能会觉得比较复杂。可查阅tailwind文档
<div id="article" class="flex-grow h-auto rounded-lg shadow-sm bg-white overflow-hidden p-10 mr-2 relative">
<img src="./gitHub.png" class="top-4 right-4 absolute w-8 h-8" alt=""/>
<p class="font-mono text-3xl font-bold tracking-wider leading-tight text-center mb-5 uppercase">
article
</p>
<div contenteditable="plaintext-only" placeholder="Write something ..." id="inp-content"
class="max-h-full break-all text-justify bg-gray-50 border-2 hover:bg-gray-100 border-gray-200 ease-out block transition-all duration-700 h-20 max-h-96 py-3 px-4 overflow-hidden font-mono cursor-auto rounded-xl"
style="outline:none;"></div>
</div>
在index.scss中将html、body标签的宽高设置为100%,让卡片可以居中在中间。你也可以在html、body标签中加入w-full、h-full类改变元素的宽高。
html,body{
width: 100%;
height: 100%;
}
模拟inpit中的placeholder,当inp-content的输入框为空时,显示定义的placeholder的值。
#inp-content[placeholder]:empty:before {
content: attr(placeholder);
color: #555;
}
当inp-content获取焦点时,将inp-content及它的父元素高度撑开到一定范围。
focus:h-96 focus:border-indigo-400
在项目根目录下的tailwind.config.js中添加以下代码。为height属性开启focus变体。
variants: {
extend: {
height: ['focus'],
},
},
文章分析卡片
即是右边的result卡片,用于显示文章的字数分析。
它与左边的article卡片效果一样,只不过是里边的内容不一样。
<div id="resultBox"
class="overflow-hidden w-2/6 flex-none rounded-lg transition-all duration-700 shadow-sm py-10 bg-white flex flex-col items-center">
<p class="font-mono text-3xl font-bold tracking-wider leading-tight text-center mb-5 uppercase">
result
</p>
</div>
将
w-2/6移除掉,替换成w-0,意思是将宽度设置为0,后续我们会通过typescript动态的控制这个卡片的宽度。
右边的饼状图是使用ECharts绘制的(相关文档),我们先安装ECharts这个库。
ECharts
安装ECharts
在终端执行以下命令,安装ECharts。
yarn add echarts
封装ECharts
在pages/index中创建一个RChart.ts文件,用来封装这个饼状图。
引入并注册饼图所需的组件。
import {
TooltipComponent,
LegendComponent,
} from 'echarts/components';
import {
PieChart, PieSeriesOption,
} from 'echarts/charts';
import {
CanvasRenderer,
} from 'echarts/renderers';
use(
[TooltipComponent, LegendComponent, PieChart, CanvasRenderer],
);
编写一个RChart类,它需要传入一个DOM元素,用于绘制饼图。
export class RChart {
private chartInstance : echarts.ECharts;
constructor(dom:HTMLElement) {
this.chartInstance = echarts.init(dom);
}
}
添加renderChart方法,用于渲染图标,需要传入文章对应的数据进行饼图渲染。是个数组类型的参数。
export type dataType = {
value: number, name: string
}
type ECOption = echarts.ComposeOption<PieSeriesOption>;
export class RChart {
// ... 忽略一些代码
public renderChart=(data:dataType[]):void => {
const option: ECOption = {
tooltip: {
trigger: 'item',
},
legend: {
top: '5%',
left: 'center',
},
series: [
{
name: '占比',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 12,
borderColor: '#fff',
borderWidth: 2,
},
label: {
show: false,
position: 'center',
formatter: '{d}%',
},
emphasis: {
scale: true,
scaleSize: 5,
label: {
show: true,
fontSize: '18',
fontWeight: 'bold',
},
},
labelLine: {
show: false,
},
data,
},
],
};
this.chartInstance.setOption(option);
}
}
在resultBox元素中创建一个饼图的渲染区域,并通过内联样式指定宽高。
<div id="resultChart" class="hidden" style="width: 20rem;height: 25rem;"></div>
jQuery
安装jQuery
在终端执行以下命令,安装jquery。
yarn add jQuery @types/jquery
配置webpack.config.ts文件,使用ProvidePlugin将$暴露出来,这样子在项目中就可以直接使用$进行使用了。
import { ProvidePlugin } from 'webpack';
plugins: [
new ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
],
在index.ts中引入我们之前写好的CheckArticle以及RChart类。
import CheckArticle from './CheckArticle';
import {
dataType, RChart,
} from './RChart';
动态交互
思路 / 步骤
- 实例化
CheckArticle、RChart类,RChart类需要传入渲染的DOM元素 - 监听输入框键盘事件
- 获取输入框元素,通过
CheckArticle类中暴露的changeContent方法更改类中文章的内容。 - 调用类中的
matchShortCode、matchLongCode方法获取代码和代码块的长度。将这两个数据转换成饼图需要的对象格式。 - 调用
RChart类中的renderChart方法进行饼图的渲染 - 判断当前输入框元素是否有元素
- 当前有内容:显示文章分析卡片
- 当前无内容:隐藏文章分析卡片
- 获取输入框元素,通过
$(($) => {
// 获取输入框元素
const inpContent = $('#inp-content');
const CA = new CheckArticle('');
const RC = new RChart(document.getElementById('resultChart')!);
inpContent.on('keyup', () => {
// 获取输入框内容
const content: string = inpContent.html();
CA.changeContent(content);
// 生成数据
const data: dataType[] = [
{
value: CA.matchShortCode(),
name: '代码长度',
},
{
value: CA.matchLongCode(),
name: '代码块长度',
},
{
value: CA.articleCount - CA.matchLongCode() - CA.matchShortCode(),
name: '文本',
}];
// 判断当前输入框内容
// 是否显示分析结果卡片
if (content) {
RC.renderChart(data);
// 添加result
$('#resultBox')
.removeClass('w-0')
.addClass('w-2/6');
$('#resultChart')
.removeClass('hidden');
$('#inp-content')
.addClass('h-96');
} else {
$('#inp-content')
.removeClass('h-96');
$('#resultChart')
.addClass('hidden');
$('#resultBox')
.removeClass('w-2/6')
.addClass('w-0');
}
});
});
到了这里,我们这个页面已经开发完毕啦!