作为一名人工智能训练师,你需要使用
artDataArray
数组中提供的指定语料进行训练,你可以用其中的词来组成任何句子来进行智能绘画的训练。
开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:
├── css
├── images
├── index.html
├── effect.gif
└── js
└── index.js
其中:
index.html
是主页面。css
是样式文件夹。images
是图片文件夹。js/index.js
是待补充的 js 文件。effect.gif
是项目最终完成的效果图。在浏览器中预览 index.html
页面效果如下:
请在 js/index.js
文件中的 TODO 部分,完善 generateAndDisplayImages
函数,实现以下目标:
根据函数参数 imageCount
和 selectedText
与已提供 artDataArray
数组中的图片相关词语进行规则匹配,并返回匹配度最高的图片数组。最佳匹配的规则为,文本内容中包含对应图片 tag
的数量最多则为匹配度最高,放在数组前面,如果多张图片匹配度相同,则任意选择匹配到的图片。
函数参数说明
imageCount
表示图片数量。selectedText
表示文本内容。artDataArray
数组说明
artDataArray
数组中每个元素为对象,包含两个属性:imageurl
和 tags
。其中,imageUrl
表示图片路径,tags
表示跟图片相关的词语,词语通过、
进行分隔。
匹配度示例:
匹配条件 | Tags | 匹配度 |
---|---|---|
一只 湖蓝色的 知更鸟 | 知更鸟、湖蓝色、十分可爱、皮克斯渲染 | 2 |
一只湖蓝色的 知更鸟 | 知更鸟、剪纸风格、个性的眉毛 | 1 |
一只湖蓝色的知更鸟 | 沙滩、遮阳伞、人、包 | 0 |
注意:测试时请使用已提供数据 tags
中的词语进行组句测试。
示例 1:
如用户输入“一只湖蓝色的知更鸟”,选择生成图片数量为 1,函数的返回值如下:
[
{ imageUrl: "images/img1.png", tags: "知更鸟、湖蓝色、十分可爱、皮克斯渲染" }
];
因为这条 tags
中的词语与文本内容,匹配量最多,匹配到了 “知更鸟”、“湖蓝色”,匹配到是数量为 2,其他 “知更鸟” 相关的图片匹配的数量为 1。
示例 2:
如用户输入“一只湖蓝色的知更鸟”,选择生成图片数量为 3,函数的返回值如下:
[
{ imageUrl: "images/img1.png", tags: "知更鸟、湖蓝色、十分可爱、皮克斯渲染" },
{ imageUrl: "images/img2.png", tags: "知更鸟、个性的眉毛、模糊毛皮" },
{ imageUrl: "images/img3.png", tags: "知更鸟、剪纸风格、个性的眉毛" }
];
最终效果可参考文件夹下面的 gif 图,图片名称为 effect.gif
(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
js/index.js
文件外的任何内容。// 获取滑块、生成按钮、图片数量显示元素、右侧面板、错误信息元素
const slider = document.querySelector('.slider');
const generateButton = document.querySelector('.generate-button');
const imageCountSpan = document.getElementById('imageCount');
const rightPanel = document.querySelector('.right-panel');
const errorMessage = document.querySelector('.error-message');
const sliderDots = document.querySelectorAll('.slider-dot');
function updateSliderDots(value) {
sliderDots.forEach((dot, index) => {
if (index < value) {
dot.style.backgroundColor = '#007bff'; // Blue
} else {
dot.style.backgroundColor = '#bbb'; // Gray
}
});
}
// 初始化图片数量为滑块的值
imageCountSpan.innerText = slider.value;
// 初始化绘画风格和文本
let imageCount = slider.value;
let selectedText = "";
// 监听滑块值变化事件
slider.addEventListener('input', () => {
imageCount = slider.value;
// 更新显示的图片数量
imageCountSpan.innerText = slider.value;
updateSliderDots(Number(imageCount))
});
// 监听绘画文本输入事件
const textarea = document.querySelector('textarea');
textarea.addEventListener('input', () => {
selectedText = textarea.value;
// 如果文本不为空,隐藏错误信息
if (selectedText) { errorMessage.style.display = 'none'; }
});
// 监听生成按钮点击事件
generateButton.addEventListener('click', () => {
// 获取生成的图片数量
// 如果文本为空,显示错误信息并返回
if (!selectedText) return errorMessage.style.display = 'block';
// 生成最佳图片的匹配数组
imgAry = generateAndDisplayImages(imageCount, selectedText);
console.log(imgAry)
// 渲染 DOM
let str = ``
imgAry.forEach((el) => {
str += `
<img src='${el.imageUrl}' />
`
})
rightPanel.innerHTML = str
});
// 假设生成的绘画数据数组为 artDataArray
const artDataArray = [
{ "imageUrl": "images/img1.jpg", "tags": "知更鸟、湖蓝色、十分可爱、皮克斯渲染" },
{ "imageUrl": "images/img2.jpg", "tags": "知更鸟、个性的眉毛、模糊毛皮" },
{ "imageUrl": "images/img3.jpg", "tags": "知更鸟、剪纸风格、个性的眉毛" },
{ "imageUrl": "images/img4.jpg", "tags": "知更鸟、油画、十分可爱、特殊的羽毛" },
{ "imageUrl": "images/img5.jpg", "tags": "男性、卡通、书、桌子" },
{ "imageUrl": "images/img6.jpg", "tags": "男性、卡通、玩具、眼镜" },
{ "imageUrl": "images/img7.jpg", "tags": "男性、卡通、玩具" },
{ "imageUrl": "images/img8.jpg", "tags": "男性、卡通、书" },
{ "imageUrl": "images/img9.jpg", "tags": "沙滩、遮阳伞、散步" },
{ "imageUrl": "images/img10.jpg", "tags": "沙滩、椰子树、一群人" },
{ "imageUrl": "images/img11.jpg", "tags": "沙滩、遮阳伞、人、包" },
{ "imageUrl": "images/img12.jpg", "tags": "沙滩、回忆、相框" }
]
/**
* @param {*} imageCount 生成的图片数量
* @param {*} selectedText 用户输入的文本
*/
function generateAndDisplayImages(imageCount, selectedText) {
let imgAry = [] // 定义最佳匹配的图片数组
// TODO:待补充代码
imgAry = artDataArray.map(items=>{
const count = items.tags.split('、').filter(item=>{
return selectedText.includes(item)
}).length
return {...items,weight:count}
}).sort((a,b)=>{return b.weight-a.weight}).slice(0,imageCount)
//TODO:END
return imgAry;
}
<!DOCTYPE html>
<html>
<head>
<title>寻找小狼人</title>
<meta charset="utf-8" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="content">
<p id="gameText"></p>
<ul></ul>
<div class="btnbox">
<button class="btn">寻找狼人</button>
</div>
</div>
<script src="./js/myarray.js"></script>
<script>
// JavaScript 代码部分
</script>
</body>
</html>
<html>
、<head>
和 <body>
标签构建基本的 HTML 页面结构。<head>
标签中设置字符编码和视口,确保页面在不同设备上正常显示,并设置页面标题为 “悠然画境”,同时引入外部 CSS 样式表。<div class="container">
作为整体容器,将页面分为左右两个面板。<div class="left-panel">
包含页面标题、数量选择滑块、绘画文本输入框、错误信息提示、生成按钮和生成数量显示。<div class="right-panel">
用于显示生成的图片。<input type="range">
滑块用于选择生成图片的数量,<textarea>
用于输入绘画文本,<button>
用于触发图片生成操作。./js/index.js
,用于实现页面的交互逻辑。/* 样式表开始 */
body {
/* 设置文本的字体及排版风格 */
font-family: Arial, sans-serif;
/* 将页面内容在垂直方向居中显示 */
display: flex;
align-items: center;
justify-content: center;
/* 设置页面高度占满视窗的100% */
height: 100vh;
/* 设置页面内容与边界的距离为0,消除默认边距 */
margin: 0;
/* 设置背景颜色 */
background-color: #f4f4f4;
}
/* 设置整体容器样式 */
.container {
/* 设置容器宽度 */
width: 730px;
/* 使用弹性布局,在主轴上居中对齐,交叉轴上顶部对齐 */
display: flex;
align-items: flex-start;
/* 设置背景颜色 */
background-color: white;
/* 添加内边距 */
padding: 20px;
/* 添加边界圆角效果 */
border-radius: 10px;
/* 添加阴影效果 */
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
/* 设置左侧面板样式 */
.left-panel {
/* 占据剩余空间的1/4,添加右侧内边距 */
flex: 1;
padding-right: 20px;
}
/* 设置右侧面板样式 */
.right-panel {
/* 占据剩余空间的3/4,设置相对定位 */
flex: 3;
position: relative;
/* 设置背景颜色 */
background-color: #f4f4f4;
/* 添加边界圆角效果 */
border-radius: 5px;
/* 设置内容溢出时的处理方式 */
overflow: hidden;
/* 使用弹性布局,将内容在多行中居中显示 */
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
/* 添加内边距 */
padding: 10px;
/* 设置最小高度 */
min-height: 300px;
/* 添加边框 */
border: 1px solid #ddd;
}
/* 设置滑块样式 */
.slider {
/* 滑块占据整个宽度 */
width: 100%;
}
/* 设置图片样式 */
img {
/* 设置图片宽高 */
width: 150px;
height: 150px;
/* 添加外边距 */
margin: 10px;
/* 图片保持比例并覆盖整个容器 */
object-fit: cover;
/* 添加边界圆角效果 */
border-radius: 5px;
/* 添加阴影效果 */
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
}
/* 设置生成按钮样式 */
.generate-button {
/* 添加外边距 */
margin-top: 10px;
/* 添加内边距 */
padding: 8px 16px;
/* 设置背景颜色 */
background-color: #007bff;
/* 设置文字颜色 */
color: white;
/* 清除边框 */
border: none;
/* 添加边界圆角效果 */
border-radius: 5px;
/* 鼠标悬停时显示手型光标 */
cursor: pointer;
}
/* 设置错误信息样式 */
.error-message {
/* 默认隐藏错误信息 */
display: none;
/* 设置文字颜色 */
color: red;
}
.diyRange {
padding: 10px 0;
position: relative;
}
.slider {
position: relative;
z-index: 100;
width: 263px;
}
.slider-dot {
position: absolute;
display: inline-block;
width: 20px;
height: 20px;
background-color: #e1e2ec;
border-radius: 50%;
z-index: 1;
}
.slider-dot:nth-of-type(1){
left: 0px;
top: 10px;
}
.slider-dot:nth-of-type(2) {
left: 82px;
top: 10px;
}
.slider-dot:nth-of-type(3) {
left: 164px;
top: 10px;
}
.slider-dot:nth-of-type(4) {
left:246px ;
top: 10px;
}
body
标签进行样式设置,包括字体、布局、高度、边距和背景颜色,使页面内容在垂直方向居中显示。.container
类进行样式设置,包括宽度、布局、背景颜色、内边距、圆角和阴影,使容器具有美观的外观。.left-panel
和 .right-panel
类进行样式设置,使用弹性布局将页面分为左右两部分,并设置各自的背景颜色、内边距、圆角等样式。.diyRange
、.slider
和 .slider-dot
类设置自定义滑块的样式,包括滑块的宽度、位置和小圆点的颜色、大小等。// 获取滑块、生成按钮、图片数量显示元素、右侧面板、错误信息元素
const slider = document.querySelector('.slider');
const generateButton = document.querySelector('.generate-button');
const imageCountSpan = document.getElementById('imageCount');
const rightPanel = document.querySelector('.right-panel');
const errorMessage = document.querySelector('.error-message');
const sliderDots = document.querySelectorAll('.slider-dot');
function updateSliderDots(value) {
sliderDots.forEach((dot, index) => {
if (index < value) {
dot.style.backgroundColor = '#007bff'; // Blue
} else {
dot.style.backgroundColor = '#bbb'; // Gray
}
});
}
// 初始化图片数量为滑块的值
imageCountSpan.innerText = slider.value;
// 初始化绘画风格和文本
let imageCount = slider.value;
let selectedText = "";
// 监听滑块值变化事件
slider.addEventListener('input', () => {
imageCount = slider.value;
// 更新显示的图片数量
imageCountSpan.innerText = slider.value;
updateSliderDots(Number(imageCount))
});
// 监听绘画文本输入事件
const textarea = document.querySelector('textarea');
textarea.addEventListener('input', () => {
selectedText = textarea.value;
// 如果文本不为空,隐藏错误信息
if (selectedText) { errorMessage.style.display = 'none'; }
});
// 监听生成按钮点击事件
generateButton.addEventListener('click', () => {
// 获取生成的图片数量
// 如果文本为空,显示错误信息并返回
if (!selectedText) return errorMessage.style.display = 'block';
// 生成最佳图片的匹配数组
imgAry = generateAndDisplayImages(imageCount, selectedText);
console.log(imgAry)
// 渲染 DOM
let str = ``
imgAry.forEach((el) => {
str += `
<img src='${el.imageUrl}' />
`
})
rightPanel.innerHTML = str
});
// 假设生成的绘画数据数组为 artDataArray
const artDataArray = [
{ "imageUrl": "images/img1.jpg", "tags": "知更鸟、湖蓝色、十分可爱、皮克斯渲染" },
{ "imageUrl": "images/img2.jpg", "tags": "知更鸟、个性的眉毛、模糊毛皮" },
{ "imageUrl": "images/img3.jpg", "tags": "知更鸟、剪纸风格、个性的眉毛" },
{ "imageUrl": "images/img4.jpg", "tags": "知更鸟、油画、十分可爱、特殊的羽毛" },
{ "imageUrl": "images/img5.jpg", "tags": "男性、卡通、书、桌子" },
{ "imageUrl": "images/img6.jpg", "tags": "男性、卡通、玩具、眼镜" },
{ "imageUrl": "images/img7.jpg", "tags": "男性、卡通、玩具" },
{ "imageUrl": "images/img8.jpg", "tags": "男性、卡通、书" },
{ "imageUrl": "images/img9.jpg", "tags": "沙滩、遮阳伞、散步" },
{ "imageUrl": "images/img10.jpg", "tags": "沙滩、椰子树、一群人" },
{ "imageUrl": "images/img11.jpg", "tags": "沙滩、遮阳伞、人、包" },
{ "imageUrl": "images/img12.jpg", "tags": "沙滩、回忆、相框" }
]
/**
* @param {*} imageCount 生成的图片数量
* @param {*} selectedText 用户输入的文本
*/
function generateAndDisplayImages(imageCount, selectedText) {
let imgAry = [] // 定义最佳匹配的图片数组
// TODO:待补充代码
imgAry = artDataArray.map(items=>{
const count = items.tags.split('、').filter(item=>{
return selectedText.includes(item)
}).length
return {...items,weight:count}
}).sort((a,b)=>{return b.weight-a.weight}).slice(0,imageCount)
//TODO:END
return imgAry;
}
document.querySelector
和 document.getElementById
方法获取页面中的滑块、生成按钮、图片数量显示元素、右侧面板、错误信息元素和滑块小圆点元素。updateSliderDots
函数,根据滑块的值更新滑块小圆点的颜色。imageCount
和 selectedText
变量。input
事件,当滑块值变化时,更新 imageCount
变量和图片数量显示元素的文本,并调用 updateSliderDots
函数更新滑块小圆点的颜色。input
事件,当用户输入文本时,更新 selectedText
变量,并在文本不为空时隐藏错误信息。click
事件,当用户点击按钮时,检查 selectedText
是否为空,如果为空则显示错误信息,否则调用 generateAndDisplayImages
函数生成最佳匹配的图片数组,并将图片渲染到右侧面板上。generateAndDisplayImages
函数,该函数接受 imageCount
和 selectedText
作为参数,通过 map
、filter
和 sort
方法对 artDataArray
中的图片进行筛选和排序,返回最佳匹配的图片数组。四、工作流程▶️
selectedText
变量,并且在文本不为空时隐藏错误信息。selectedText
是否为空,如果为空则显示错误信息,否则根据 imageCount
和 selectedText
调用 generateAndDisplayImages
函数生成最佳匹配的图片数组。