地图组件
2025-8-22
效果预览
使用方法
数据生成的逻辑
目前的默认状态。
你可以手动规定每一个地点的数据,包括地点、图标、desc、event、charactor、坐标,并且当你前往任一地点后,会根据剧情生成新内容,所有地点的event、charactor都会重新生成。你点击前往按钮后,会在酒馆中自动发出前往地点的指令。完全随机状态。
你可以只写每一个地点的坐标和图标,其他内容都由AI随机生成。完全固定状态。
你可以手动规定每一个地点的数据,包括地点、图标、desc、event、charactor、坐标,并且他们绝对不会改变。(这一点需要你手动调整世界书中「你必须按照我制定的内容生成。未指定内容的部分,你可以随机生成,当前往任一地点后,所有地点的event、charactor都得重新生成。事件发生后请根据剧情生成新事件。」的部分,并且改成「你必须按照我制定的内容生成,并且不论发生什么绝对不能更改。」
底图的图标
为你的故事选择一张合适的地图底图,将它的网址替换到在“地图模板1-替换为”中“神经岛地图”下方的webp链接(https://cdn.mujian.me/tuchuang/68987fc97b7e3.webp),你需要将图片上传到图床,并获取一个URL地址,这里填的就是他的URL的地址。
底图的名称
在“地图模板1-替换为”中,“神津岛地图”就是底图的名称,你可以修改它,但不要删除它。
图标与坐标
为你故事中的地点选择合适的坐标位置,你可以先阅读一下世界书中【数据生成规则】的部分,理解每一个字段的作用。整体来说,一个坐标有以下几个字段:地点、图标、desc、event、charactor、坐标。
- 地点:地点的名称(例如:“市中心”、“废弃的灯塔”)
- 图标:也是图片的URL地址,但在这里只需要替换图标的名称,比如68988290c3a89.png,图标会自动从代码块中获取。
- desc:用一句话简要描述该地点,理论上来说,地点描述在多次生成地图时应该完全相同,如果你需要让AI随机生成,可以把这句话在世界书里删除
- event:该地点的一个正在发生的特殊事件、传闻或情节
坐标的范围是从0-100,分别对应着百分比位置上的横坐标和纵坐标。 底图左上角坐标为[0, 0],右上角坐标为[100, 0],右下角坐标为[100, 100],图片中央为[50, 50]。
颜色与默认文本
在“地图模板1-替换为”中,你可以修改颜色。在“地图模板2-替换为”中,你可以修改默认文本(地点描述、地点事件、角色)。
世界书
<MapGeneration>
当用户输入“查看地图”时,你必须,且只能,生成以下 <MapBlock> 格式的数据(包括标签本身)。绝对禁止添加任何对话、解释、标点符号或在此格式之外的任何文本。这是一项关键的技术指令。
<MapBlock>
[MapLoc|鸣泷川神宫|ic.png|desc|event|charactor|42.3|89.1|current]
[MapLoc|村落|ic.png|desc2|event2|charactor2|12.3|49.1|]
</MapBlock>
【数据生成规则】
1. **每行格式**:由一对方括号包裹,中间使用竖线分隔以下内容:
- 固定文本:“MapLoc”,请直接输出“MapLoc”,不要多也不要少;
- 地点:地点的名称(例如:“市中心”、“废弃的灯塔”);
- 地点标记的图标;
- desc:用一句话简要描述该地点,请注意,地点描述在多次生成地图时应该完全相同;
- event:该地点的一个正在发生的特殊事件、传闻或情节(例如:“传闻灯塔下埋藏着海盗的宝藏,这里正在举办寻宝大会”);
- charactor:在该地点遇到的一个关键NPC(NPC主要是{{char}}或故事里出现的其他角色,但一定不能是{{user}},你可以视情况安排合适的NPC登场,但绝对不要让{{char}}同时出现在多个地方)。必须注意,相关角色一定不能是{{user}},且一定要生成一个相关角色;
- 标记在地图上的横坐标;
- 标记在地图上的纵坐标;
- {{user}}是否在这个地点,如果在则输出"current",否则输出空字符串。
2. 请生成以下几个地点,每个地点输出一对方括号,他们默认使用`68988290c3a89.png`作为图标。你必须按照我制定的内容生成。未指定内容的部分,你可以随机生成,当{{user}}前往任一地点后,所有地点的event、charactor都得重新生成。事件发生后请根据剧情生成新事件。
- 鸣泷川神宫:坐标是[61,42],图标是68988073e8fff.png。desc:“一个巨大、古老封印的守护地坐落于山顶,是岛上所有信仰的核心”。event:“三年坂家族的族人们正在拼尽全力修复着结界”。charactor:“三年坂家族的族人”。
- 村落:坐标是[20,38],图标是6898809fbe1c9.png。未指定内容。
- 不详的大门:坐标是[40,38]。图标是689880b946159.png。未指定内容。
- 商店街:坐标是[68,83],图标是689880a906c68.png。未指定内容。
- 高塔:坐标是[82,32],图标是689880e0cb933.png。未指定内容。
- 坟墓:坐标是[60,12],图标是689880df284b7.png。未指定内容。
- 游轮:坐标是[37,65],图标是68988746eed43.png。未指定内容。
- 宗介的研究室:坐标是[15,12],图标是689887cd2d66b.png。未指定内容。
- 陨石落点:坐标是[42,17],图标是68988860cb655.png。未指定内容。
- 医院:坐标是[24,57],图标是689888d5472eb.png。未指定内容。
- 藏宝处:坐标是[85,60],图标是6898894f1d930.png。未指定内容。
- 警察局:坐标是[60,62],图标是68988b01efb91.png。未指定内容。
3. **内容生成逻辑**:所有数据内容,都必须基于当前的剧情、世界观和氛围来进行现场创造。请确保多样性。
4. **最终检查**:在输出前,请再次确认你的回复。确保它严格遵守 <MapBlock> 格式,不包含任何额外文本。严格遵守,这不是一个可选项。
<example>
对上面提供的<MapBlock>做举例说明:
1. 定义了两个地点
a. [MapLoc|鸣泷川神宫|ic.png|混乱的中心。一座古朴的神社矗立于此,周围散发着肉眼可见的波动,似乎是结界的力量|修复结界,需要更多的灵力|三年坂家族的族人们|42.3|89.1|current]
b. [MapLoc|村落|ic.png|岛民们居住的场所,原本是平静安详的村落,现在似乎充满了混乱|物资收集|剩余清醒的岛民们|12.3|49.1|]
</example>
</MapGeneration>地图模板1-正则
<MapBlock>([^<]*)</MapBlock>地图模板1-替换成
```html
<!doctype html>
<html>
<head>
<script src="https://cdn.mujian.me/libs/jquery%403.7.1/jquery.min.js"></script>
<script src="https://cdn.mujian.me/libs/%40tailwindcss/browser%404.1.11/dist/index.global.js"></script>
<meta name="viewport" content="width=device-width" />
<style type="text/tailwindcss">
@theme {
--color-base: #eff1f5;
--color-text: #4c4f69;
}
</style>
<style>
#app {
max-width: 800px;
}
.marker {
position: absolute;
width: 36px;
height: 44px;
margin-top: -18px;
margin-left: -18px;
display: flex;
flex-direction: column;
align-items: center;
cursor: default;
}
.marker .current-sign {
display: none;
}
.marker.current .current-sign {
display: unset;
position: absolute;
width: 16px;
left: -6px;
top: -14px;
}
.marker > img {
width: 100%;
border-radius: 50%;
margin-bottom: 0.5em;
}
.marker .bubble {
font-size: 12px;
background: rgba(30, 30, 46, 0.7);
color: white;
padding: 0.25em 0.5em;
border-radius: 5px;
white-space: nowrap;
position: relative;
backdrop-filter: blur(8px);
}
.marker .detail {
display: none;
width: 15em;
overflow: auto;
}
.marker .detail button {
color: #89b4fa;
cursor: pointer;
}
.marker.active .bubble {
z-index: 1;
}
.marker.active .name {
font-weight: bold;
}
.marker.active .detail {
display: block;
position: absolute;
}
</style>
</head>
<body>
<div id="app">
<div
id="header"
class="p-4 flex items-center justify-between cursor-default rounded-t-lg bg-base text-text"
>
<div id="title">神津岛地图</div>
<button id="collapse-btn" class="cursor-pointer">折叠</button>
</div>
<div id="content" class="relative">
<img
id="bg"
class="block w-full rounded-b-lg"
src="https://cdn.mujian.me/tuchuang/68987fc97b7e3.webp"
/>
<div id="markers" class="absolute top-0 right-0 bottom-0 left-0">
$1
</div>
</div>
</div>
<script>
$(".marker button").click((ev) => {
let name = ev.target.parentElement.children[0].textContent;
window.triggerSlash?.(`/send 前往地点:${name}| /trigger`);
});
$(".marker").each(function () {
let l = parseInt(this.style.left);
let t = parseInt(this.style.top);
$(this)
.find(".detail")
.addClass(l < 50 ? "left-0" : "right-0")
.addClass(t < 50 ? "top-0" : "bottom-0");
});
$(".marker").on("mouseenter", function (e) {
let that = $(this);
setTimeout(() => {
that.addClass("active");
});
});
$(".marker").on("mouseleave", function (e) {
$(this).removeClass("active");
});
$("#bg").on("load", function () {
let width = $(this).get()[0].offsetWidth;
let height = $(this).get()[0].offsetHeight;
$(".detail").each(function () {
$(this).css("max-width", width * 0.4);
$(this).css("max-height", height * 0.4);
});
console.log($(this).get()[0].offsetWidth);
});
let showMap = true;
$("#collapse-btn").click(() => {
showMap = !showMap;
$("#content").css("display", showMap ? "block" : "none");
$("#header")[showMap ? "removeClass" : "addClass"]("rounded-b-lg");
$("#collapse-btn").text(showMap ? "折叠" : "展开");
});
</script>
</body>
</html>
```地图模板2-正则
/\[MapLoc\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^|]*)\|([^\]]*)\]/g地图模板2-替换为
<div class="marker $8" style="left: $6%; top: $7%">
<img src="https://cdn.mujian.me/tuchuang/$2" />
<div class="bubble relative">
<img
class="current-sign"
src="https://cdn.mujian.me/tuchuang/688b3fc147d4b.gif"
/>
<div class="name">$1</div>
<div class="bubble detail">
<div class="name">$1</div>
<div class="mt-1">
<span class="font-bold opacity-70">地点描述:</span
><span class="whitespace-break-spaces break-all"
>$3</span
>
</div>
<div class="mt-1">
<span class="font-bold opacity-70">地点事件:</span
><span class="whitespace-break-spaces break-all">$4</span>
</div>
<div class="mt-1">
<span class="font-bold opacity-70">角色:</span
><span class="whitespace-break-spaces break-all"
>$5</span
>
</div>
<button class="mt-1">
>>>>前往>>>>
</button>
</div>
</div>
</div>