如何在Jekyll博客中实现基于2D位置(距离)的搜索功能?
问题描述
我有一个使用Simple-Jekyll-Search库实现搜索功能的Jekyll站点,该站点是包含大量条目的目录,这些条目均带有(x, y)位置属性。我的search.md文件内容如下:
--- layout: page title: Search permalink: /search/ --- <div id="search-container"> <input type="text" id="search-input" placeholder="Search the catalogue..."> <ul id="results-container"></ul> </div> <script src="{{ site.baseurl }}/assets/simple-jekyll-search.min.js" type="text/javascript"></script> <script> SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), searchResultTemplate: '<div style="text-align: left !important;"><a href="{url}"><h1 style="text-align:left !important;">{title}</h1></a></div>', json: '{{ site.baseurl }}/search.json' }); </script>
当前文字搜索功能运行正常,但我还需要实现基于距离的搜索,具体需求为:
- 用户输入一个2D位置坐标(x, y)
- 展示目录中所有位置处于该坐标加上固定搜索半径范围内的条目
我想要实现类似参考站点的效果,但我不会编写JavaScript代码,请问是否有现成的库可以实现该功能?
解决方案
Simple-Jekyll-Search本身不支持坐标距离搜索,不过你可以用Fuse.js这个轻量级搜索库来实现,它支持文本搜索和自定义筛选逻辑,配置简单,不需要写复杂代码:
步骤1:准备Fuse.js
下载压缩版的fuse.min.js,放到你的站点assets目录下。
步骤2:替换search.md内容
把原有的search.md代码替换成以下内容,它同时支持文本搜索和坐标距离搜索:
--- layout: page title: Search permalink: /search/ --- <div id="search-container"> <input type="text" id="search-input" placeholder="搜索关键词,或输入坐标如 100,200"> <input type="number" id="radius-input" placeholder="搜索半径" value="10"> <ul id="results-container"></ul> </div> <script src="{{ site.baseurl }}/assets/fuse.min.js"></script> <script> // 加载搜索数据 fetch('{{ site.baseurl }}/search.json') .then(res => res.json()) .then(data => { // 配置文本搜索规则 const fuse = new Fuse(data, { keys: ['title', 'content'], includeScore: true, threshold: 0.3 }); const searchInput = document.getElementById('search-input'); const radiusInput = document.getElementById('radius-input'); const resultsContainer = document.getElementById('results-container'); // 核心搜索逻辑 function runSearch() { const query = searchInput.value.trim(); const radius = parseFloat(radiusInput.value) || 10; resultsContainer.innerHTML = ''; // 判断输入是否为坐标格式(逗号分隔的数字) const coordRegex = /^(-?\d+(\.\d+)?),\s*(-?\d+(\.\d+)?)$/; if (coordRegex.test(query)) { const [, xStr, , yStr] = query.match(coordRegex); const inputX = parseFloat(xStr); const inputY = parseFloat(yStr); // 筛选半径范围内的条目(假设条目有x、y字段) const matches = data.filter(item => { const dx = inputX - item.x; const dy = inputY - item.y; const distance = Math.sqrt(dx*dx + dy*dy); return distance <= radius; }); // 渲染结果 matches.forEach(item => { const li = document.createElement('li'); li.innerHTML = `<div style="text-align: left !important;"><a href="${item.url}"><h1 style="text-align:left !important;">${item.title}</h1></a><p>坐标: (${item.x}, ${item.y})</p></div>`; resultsContainer.appendChild(li); }); } else { // 执行普通文本搜索 const matches = fuse.search(query); matches.forEach(result => { const li = document.createElement('li'); li.innerHTML = `<div style="text-align: left !important;"><a href="${result.item.url}"><h1 style="text-align:left !important;">${result.item.title}</h1></a></div>`; resultsContainer.appendChild(li); }); } } // 输入变化时触发搜索 searchInput.addEventListener('input', runSearch); radiusInput.addEventListener('change', runSearch); }); </script>
步骤3:确保search.json包含坐标字段
修改你生成search.json的Jekyll模板,确保每个条目都包含x和y字段,比如:
--- layout: null --- [ {% for item in site.catalogue %} { "title": "{{ item.title | escape }}", "url": "{{ item.url | absolute_url }}", "content": "{{ item.content | strip_html | escape }}", "x": {{ item.x }}, "y": {{ item.y }} }{% unless forloop.last %},{% endunless %} {% endfor %} ]
这样配置后,用户输入类似123.45, 67.89的坐标,就能看到该位置指定半径内的所有条目,同时保留原有的文本搜索功能。
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

