整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

利用Css3样式属性Cursor来更换自定义个性化鼠

利用Css3样式属性Cursor来更换自定义个性化鼠标指针(光标)

而今,我们纵向的回顾整个大前端的历史,不难发现,人们对前端的审美要求越来越高,越来越严苛,与此同时,人们对追求美的体验是也极致的,从理性到感性,从平面到几何,从现实到虚拟,所以从某种角度来说,作为前端工程师,他们所追求的东西往往和人类软件核心理念南辕北辙,因为人类的终极追求是个性,绝不是共性,换句话说,大家都一样就不好玩儿了。

那么作为web前端,追求个性的手段手段之一就是鼠标指针的更换,早在css2时代,Cursor属性就可以对象鼠标指针光标进行控制,可以根据自身需要选择设置鼠标指针样式,代码如下:

<head>
    <title>cursor属性</title>
</head>
<body>
    <p>请把鼠标移动到单词上,可以看到鼠标指针发生变化:</p>
    <span style="cursor:auto">Auto......</span><br />
    <span style="cursor:crosshair">Crosshair......</span><br />
    <span style="cursor:default">Default......</span><br />
    <span style="cursor:pointer">Pointer......</span><br />
    <span style="cursor:move">Move......</span><br />
    <span style="cursor:e-resize">e-resize......</span><br />
    <span style="cursor:ne-resize">ne-resize......</span><br />
    <span style="cursor:nw-resize">nw-resize......</span><br />
    <span style="cursor:n-resize">n-resize......</span><br />
    <span style="cursor:se-resize">se-resize......</span><br />
    <span style="cursor:sw-resize">sw-resize......</span><br />
    <span style="cursor:s-resize">s-resize......</span><br />
    <span style="cursor:w-resize">w-resize......</span><br />
    <span style="cursor:text">text......</span><br />
    <span style="cursor:wait">wait......</span><br />
    <span style="cursor:help">help......</span>
</body>
</html>

不过这些属性仅仅是更换系统自定义的一些默认样式,毫无新意,当然也不能满足所有用户的需求,特别对于一些追求时尚和个性化的Web应用。因此,CSS允许用户创建自己的鼠标光标图片,并保存为 .cur 的光标文件,然后通过 cursor属性来使用它们。如:

cursor: url(cursors/cursor.cur) ;


上述规则表示,要求浏览器加载名称为 cursor.cur 光标文件,并将它用作鼠标光标。当然,浏览器也有可能不支持 .cur 格式的光标文件,或光标文件无法正常加载。因此,大多数浏览器要求必须指定一个备用的光标,否则,cursor属性无效。如:

cursor: url(cursors/cursor.cur), pointer;

除了更换鼠标指针,我们也可以稍加一些变化,比如鼠标悬停在超链接的时候,语义化操作往往需要给用户一点提示:

a:hover, a:focus, a:active, a.active {
	color: #fec503;
	cursor:url(././mouse/breeze/Hand.cur), pointer;
}


效果是下面这样:

这里我使用的鼠标风格是在业界鼎鼎有名的 Breeze

当然了由于不同浏览器所支持的光标文件格式不尽相同,Opera和IE仅支持 .cur 格式,Firefox、Chrome和Safari既支持 .cur 格式,也支持常见的 .jpg、.gif、.jpg 等格式。

所以从通用性的角度来看,.cur格式是最保险的,不过也不用担心,如果出现不兼容的情况,系统会选择默认的样式。

值得一提的是,对于.cur文件来说,尺寸最好选择不大于于32*32像素的,因为通过样式进行样式的加载会损耗一些网页性能,同时过大的光标也会影响用户的点选。

最后,如果手里有.cur的鼠标光标图片样式,这些图片不仅仅可以应用在web网站上,像电脑系统也可以使用比如win10,ubuntu或者mac,这里推荐一个鼠标指针风格网站的下载地址:https://zhutix.com/tag/cursors/ 这上面的鼠标指针风格不能说清新脱俗吧,但是也比那些烂大街的杀马特造型要好看多了。

S 鼠标框选(页面选择)时返回对应的 HTML 或文案内容

一、需求背景

1、项目需求

当用户进行鼠标框选选择了页面上的内容时,把选择的内容进行上报。

2、需求解析

虽然这需求就一句话的事,但是很显然,没那么简单...

因为鼠标框选说起来简单,就是选择的内容,但是这包含很多中情况,比如:只选择文案、选择图片、选择输入框、输入框中的内容选择、iframe、等。

简单总结,分为以下几点:

  1. 选择文案时
  2. 选择图片、svg、iframe、video、audio 等标签时
  3. 选择 input、select、textarea 等标签时
  4. 选择 input、textarea 标签内容时
  5. 选择类似 字符时
  6. 键盘全选时
  7. 鼠标右键选择
  8. 以上各模块结合时
  9. 当包含标签的时候,返回 html 结构,只有文本时返回文本内容

二、技术要点

鼠标框选包含以下几点:

  1. debounce 防抖
  2. addEventListener 事件监听
  3. Range 对象
  4. Selection 对象

1、debounce

老生常谈的技术点了,这里不能用节流,因为肯定不能你鼠标选择的时候,隔一段时间返回一段内容,肯定是选择之后一起返回。

这里用 debounce 主要也是用在事件监听和事件处理上。

  • 【debounce 掘金】
  • 【debounce CSDN】

2、addEventListener

事件监听,因为鼠标选择,不仅仅是鼠标按下到鼠标抬起,还包括双击、右键、全选。

需要使用事件监听对事件作处理。

  • 【addEventListener MDN】

3、Range

Range 接口表示一个包含节点与文本节点的一部分的文档片段。

Range 是浏览器原生的对象。

3.1. 创建 Range 实例,并设置起始位置

<body>
  <ul>
    <li>Vite</li>
    <li>Vue</li>
    <li>React</li>
    <li>VitePress</li>
    <li>NaiveUI</li>
  </ul>
</body>
<script>
  // 创建 Range 对象
  const range=new Range()
  const liDoms=document.querySelectorAll("li");
  // Range 起始位置在 li 2
  range.setStartBefore(liDoms[1]);
  // Range 结束位置在 li 3
  range.setEndAfter(liDoms[2]);
  // 获取 selection 对象
  const selection=window.getSelection();
  // 添加光标选择的范围
  selection.addRange(range);
</script>


可以看到,选择内容为第二行和第三行

3.1.1 浏览器兼容情况


3.2. Range 属性

  1. startContainer:起始节点。
  2. startOffset:起始节点偏移量。
  3. endContainer:结束节点。
  4. endOffset:结束节点偏移量。
  5. collapsed:范围的开始和结束是否为同一点。
  6. commonAncestorContainer:返回完整包含 startContainer 和 endContainer 的最深一级的节点。

3.2.1. 用我们上面创建的实例来看下 range 属性的值


3.2.2. 如果我们只选择文本内容时

只选择 li 中的 itePres


可以看出 range 属性对应的值


3.3. Range 方法

  1. cloneContents():复制范围内容,并将复制的内容作为 DocumentFragment 返回。
  2. cloneRange():创建一个具有相同起点/终点的新范围, 非引用,可以随意改变,不会影响另一方。
  3. collapse(toStart):如果 toStart=true 则设置 end=start,否则设置 start=end,从而折叠范围。
  4. compareBoundaryPoints(how, sourceRange):两个范围边界点进行比较,返回一个数字 -1、0、1。
  5. comparePoint(referenceNode, offset):返回-1、0、1具体取决于 是 referenceNode 在 之前、相同还是之后。
  6. createContextualFragment(tagString):返回一个 DocumentFragment。
  7. deleteContents():删除框选的内容。
  8. extractContents():从文档中删除范围内容,并将删除的内容作为 DocumentFragment 返回。
  9. getBoundingClientRect():和 dom 一样,返回 DOMRect 对象。
  10. getClientRects():返回可迭代的对象序列 DOMRect。
  11. insertNode(node):在范围的起始处将 node 插入文档。
  12. intersectsNode(referenceNode):判断与给定的 node 是否相交。
  13. selectNode(node):设置范围以选择整个 node。
  14. selectNodeContents(node):设置范围以选择整个 node 的内容。
  15. setStart(startNode, startOffset):设置起点。
  16. setEnd(endNode, endOffset):设置终点。
  17. setStartBefore(node):将起点设置在 node 前面。
  18. setStartAfter(node):将起点设置在 node 后面。
  19. setEndBefore(node):将终点设置为 node 前面。
  20. setEndAfter(node):将终点设置为 node 后面。
  21. surroundContents(node):使用 node 将所选范围内容包裹起来。

3.4. 创建 Range 的方法

3.4.1. Document.createRange

const range=document.createRange();

3.4.2. Selection 的 getRangeAt() 方法

const range=window.getSelection().getRangeAt(0)

3.4.3. caretRangeFromPoint() 方法

if (document.caretRangeFromPoint) {
    range=document.caretRangeFromPoint(e.clientX, e.clientY);
}

3.4.4. Range() 构造函数

const range=new Range()

3.5. Range 兼容性


4、Selection

Selection 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。

4.1. 获取文本对象

window.getSelection()



4.2. Selection 术语

4.2.1. 锚点 (anchor)

锚指的是一个选区的起始点(不同于 HTML 中的锚点链接)。当我们使用鼠标框选一个区域的时候,锚点就是我们鼠标按下瞬间的那个点。在用户拖动鼠标时,锚点是不会变的。

4.2.2. 焦点 (focus)

选区的焦点是该选区的终点,当你用鼠标框选一个选区的时候,焦点是你的鼠标松开瞬间所记录的那个点。随着用户拖动鼠标,焦点的位置会随着改变。

4.2.3. 范围 (range)

范围指的是文档中连续的一部分。一个范围包括整个节点,也可以包含节点的一部分,例如文本节点的一部分。用户通常下只能选择一个范围,但是有的时候用户也有可能选择多个范围。

4.2.4. 可编辑元素 (editing host)

一个用户可编辑的元素(例如一个使用 contenteditable 的 HTML 元素,或是在启用了 designMode 的 Document 的子元素)。

4.3. Selection 的属性

首先要清楚,选择的起点称为锚点(anchor),终点称为焦点(focus)。

  1. anchorNode:选择的起始节点。
  2. anchorOffset:选择开始的 anchorNode 中的偏移量。
  3. focusNode:选择的结束节点。
  4. focusOffset:选择开始处 focusNode 的偏移量。
  5. isCollapsed:如果未选择任何内容(空范围)或不存在,则为 true。
  6. rangeCount:选择中的范围数,之前说过,除 Firefox 外,其他浏览器最多为1。
  7. type:类型:None、Caret、Range

4.4. Selection 方法

  1. addRange(range): 将一个 Range 对象添加到当前选区。
  2. collapse(node, offset): 将选区折叠到指定的节点和偏移位置。
  3. collapseToEnd(): 将选区折叠到当前选区的末尾。
  4. collapseToStart(): 将选区折叠到当前选区的起始位置。
  5. containsNode(node, partlyContained): 判断选区是否包含指定的节点,可以选择是否部分包含。
  6. deleteFromDocument(): 从文档中删除选区内容。
  7. empty(): 从选区中移除所有范围(同 `removeAllRanges()``,已废弃)。
  8. extend(node, offset): 将选区的焦点节点扩展到指定的节点和偏移位置。
  9. getRangeAt(index): 返回选区中指定索引处的 Range 对象。
  10. removeAllRanges(): 移除所有选区中的范围。
  11. removeRange(range): 从选区中移除指定的 Range 对象。
  12. selectAllChildren(node): 选中指定节点的所有子节点。
  13. setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset): 设置选区的起始和结束节点及偏移位置。
  14. setPosition(node, offset):collapse 的别名

4.5. Selection 兼容性


三、项目实现

1、实现思路

  1. 先获取选择的内容,开发 getSelectContent 函数
  2. 对获取的内容进行判断,是否存在 selection 实例,没有直接返回 null
  3. 判断 selection 实例的 isCollapsed 属性 没有选中,对 selection 进行 toString().trim() 操作,判断内容 有内容,直接返回 text 类型 无内容,返回 null 有选中,则判断内容
  4. 判断选中的内容有没有节点 没有节点,则和没有选中一样处理,进行 toString().trim() 操作,判断内容 有内容,直接返回 text 类型 无内容,返回 null 有节点,进行 toString().trim() 操作,判断内容 没有内容,判断是否有特殊节点 有 'iframe', 'svg', 'img', 'audio', 'video' 节点,返回 html 类型 有 'input', 'textarea', 'select',判断 value 值,是否存在 存在:返回 html 类型 不存在:返回 null 没有特殊节点,返回 null 有内容,返回 html 类型
  5. 对鼠标 mousedown、mouseup 事件和 selectionchange、contextmenu、dblclick 事件进行监听,触发 getSelectContent 函数
  6. 在需要的地方进行 debounce 防抖处理

2、简易流程图


2、Debounce 方法实现

2.1. JS

function debounce (fn, time=500) {
  let timeout=null; // 创建一个标记用来存放定时器的返回值
  return function () {
    clearTimeout(timeout) // 每当触发时,把前一个 定时器 clear 掉
    timeout=setTimeout(()=> { // 创建一个新的 定时器,并赋值给 timeout
      fn.apply(this, arguments)
    }, time)
  }
}

2.2. TS

/**
 * debounce 函数类型
 */
type DebouncedFunction<F extends (...args: any[])=> any>=(...args: Parameters<F>)=> void
/**
 * debounce 防抖函数
 * @param {Function} func 函数
 * @param {number} wait 等待时间
 * @param {false} immediate 是否立即执行
 * @returns {DebouncedFunction}
 */
function debounce<F extends (...args: any[])=> any>(
  func: F,
  wait=500,
  immediate=false
): DebouncedFunction<F> {
  let timeout: ReturnType<typeof setTimeout> | null
  return function (this: ThisParameterType<F>, ...args: Parameters<F>) {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const context=this
    const later=function () {
      timeout=null
      if (!immediate) {
        func.apply(context, args)
      }
    }
    const callNow=immediate && !timeout
    if (timeout) {
      clearTimeout(timeout)
    }
    timeout=setTimeout(later, wait)
    if (callNow) {
      func.apply(context, args)
    }
  }
}

3、获取选择的文本/html 元素

3.1. 获取文本/html 元素

nterface IGetSelectContentProps {
  type: 'html' | 'text'
  content: string
}
/**
 * 获取选择的内容
 * @returns {null | IGetSelectContentProps} 返回选择的内容
 */
const getSelectContent=(): null | IGetSelectContentProps=> {
  const selection=window.getSelection()
  if (selection) {
    // 1. 是焦点在 input 输入框
    // 2. 没有选中
    // 3. 选择的是输入框
    if (selection.isCollapsed) {
      return selection.toString().trim().length
        ? {
            type: 'text',
            content: selection.toString().trim()
          }
        : null
    }
    // 获取选择范围
    const range=selection.getRangeAt(0)
    // 获取选择内容
    const rangeClone=range.cloneContents()
    // 判断选择内容里面有没有节点
    if (rangeClone.childElementCount > 0) {
      // 创建 div 标签
      const container=document.createElement('div')
      // div 标签 append 复制节点
      container.appendChild(rangeClone)
      // 如果复制的内容长度为 0
      if (!selection.toString().trim().length) {
        // 判断是否有选择特殊节点
        const isSpNode=hasSpNode(container)
        return isSpNode
          ? {
              type: 'html',
              content: container.innerHTML
            }
          : null
      }
      return {
        type: 'html',
        content: container.innerHTML
      }
    } else {
      return selection.toString().trim().length
        ? {
            type: 'text',
            content: selection.toString().trim()
          }
        : null
    }
  } else {
    return null
  }
}
/**
 * 判断是否包含特殊元素
 * @param {Element} parent 父元素
 * @returns {boolean} 是否包含特殊元素
 */
const hasSpNode=(parent: Element): boolean=> {
  const nodeNameList=['iframe', 'svg', 'img', 'audio', 'video']
  const inpList=['input', 'textarea', 'select']
  return Array.from(parent.children).some((node)=> {
    if (nodeNameList.includes(node.nodeName.toLocaleLowerCase())) return true
    if (
      inpList.includes(node.nodeName.toLocaleLowerCase()) &&
      (node as HTMLInputElement).value.trim().length
    )
      return true
    if (node.children) {
      return hasSpNode(node)
    }
    return false
  })
}

3.2. 只需要文本

/**
 * 获取框选的文案内容
 * @returns {string} 返回框选的内容
 */
const getSelectTextContent=(): string=> {
  const selection=window.getSelection()
  return selection?.toString().trim() || ''
}

4、添加事件监听

// 是否时鼠标点击动作
let selectionchangeMouseTrack: boolean=false
const selectionChangeFun=debounce(()=> {
  const selectContent=getSelectContent()
  console.log('selectContent', selectContent)
  // todo... 处理上报
  selectionchangeMouseTrack=false
})
// 添加 mousedown 监听事件
document.addEventListener('mousedown', ()=> {
  selectionchangeMouseTrack=true
})
// 添加 mouseup 监听事件
document.addEventListener(
  'mouseup',
  debounce(()=> {
    selectionChangeFun()
  }, 100)
)
// 添加 selectionchange 监听事件
document.addEventListener(
  'selectionchange',
  debounce(()=> {
    if (selectionchangeMouseTrack) return
    selectionChangeFun()
  })
)
// 添加 dblclick 监听事件
document.addEventListener('dblclick', ()=> {
  selectionChangeFun()
})
// 添加 contextmenu 监听事件
document.addEventListener(
  'contextmenu',
  debounce(()=> {
    selectionChangeFun()
  })
)

也可以进行封装

/**
 * addEventlistener function 类型
 */
export interface IEventHandlerProps {
  [eventName: string]: EventListenerOrEventListenerObject
}

let selectionchangeMouseTrack: boolean=false
const eventHandlers: IEventHandlerProps={
  // 鼠标 down 事件
  mousedown: ()=> {
    selectionchangeMouseTrack=true
  },
  // 鼠标 up 事件
  mouseup: debounce(()=> selectionChangeFun(), 100),
  // 选择事件
  selectionchange:  debounce(()=> {
    if (selectionchangeMouseTrack) return
    selectionChangeFun()
  }),
  // 双击事件
  dblclick: ()=> selectionChangeFun(),
  // 右键事件
  contextmenu: debounce(()=> selectionChangeFun())
}
Object.keys(eventHandlers).forEach((event)=> {
  document.addEventListener(event, eventHandlers[event])
})

5、返回内容

5.1. 纯文本内容


5.2. html 格式


6. 完整 JS 代码

function debounce (fn, time=500) {
  let timeout=null; // 创建一个标记用来存放定时器的返回值
  return function () {
    clearTimeout(timeout) // 每当触发时,把前一个 定时器 clear 掉
    timeout=setTimeout(()=> { // 创建一个新的 定时器,并赋值给 timeout
      fn.apply(this, arguments)
    }, time)
  }
}

let selectionchangeMouseTrack=false
document.addEventListener('mousedown', (e)=> {
  selectionchangeMouseTrack=true
  console.log('mousedown', e)
})
document.addEventListener('mouseup', debounce((e)=> {
  console.log('mouseup', e)
  selectionChangeFun()
}, 100))
document.addEventListener('selectionchange', debounce((e)=> {
  console.log('selectionchange', e)
  if (selectionchangeMouseTrack) return
  selectionChangeFun()
}))
document.addEventListener('dblclick', (e)=> {
  console.log('dblclick', e)
  selectionChangeFun()
})
document.addEventListener('contextmenu',debounce(()=> {
  selectionChangeFun()
}))

const selectionChangeFun=debounce(()=> {
  const selectContent=getSelectContent()
  selectionchangeMouseTrack=false
  console.log('selectContent', selectContent)
})

const getSelectContent=()=> {
  const selection=window.getSelection();
  if (selection) {
    // 1. 是焦点在 input 输入框
    // 2. 没有选中
    // 3. 选择的是输入框
    if (selection.isCollapsed) {
      return selection.toString().trim().length ? {
        type: 'text',
        content: selection.toString().trim()
      } : null
    }
    // 获取选择范围
    const range=selection.getRangeAt(0);
    // 获取选择内容
    const rangeClone=range.cloneContents()
    // 判断选择内容里面有没有节点
    if (rangeClone.childElementCount > 0) {
      const container=document.createElement('div');
      container.appendChild(rangeClone);
      if (!selection.toString().trim().length) {
        const hasSpNode=getSpNode(container)
        return hasSpNode ? {
          type: 'html',
          content: container.innerHTML
        } : null
      }
      return {
        type: 'html',
        content: container.innerHTML
      }
    } else {
      return selection.toString().trim().length ? {
        type: 'text',
        content: selection.toString().trim()
      } : null
    }
  } else {
    return null
  }
}

const getSpNode=(parent)=> {
  const nodeNameList=['iframe', 'svg', 'img', 'audio', 'video']
  const inpList=['input', 'textarea', 'select']
  return Array.from(parent.children).some((node)=> {
    if (nodeNameList.includes(node.nodeName.toLocaleLowerCase())) return true
    if (inpList.includes(node.nodeName.toLocaleLowerCase()) && node.value.trim().length) return true
    if (node.children) {
      return getSpNode(node)
    }
    return false
  })
}

四、总结

  1. 鼠标框选上报能监控用户在页面的行为,能为后续的数据分析等提供便利
  2. 基于 JS 中的 Selection 和 Range 实现的,使用原生 JS
  3. 涉及到的操作比较多,包含键盘、鼠标右键、全选等
  4. 能对框选的内容进行分类,区别 html 和 text,更方便的看出用户选择了哪些内容

人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。

产品设计时细节是产品经理最头疼的问题,一个button,一个链接都要考虑太多的细节问题。作者整理了常见的一些功能设计问题,一篇文章看懂这些功能设计。来学习吧。

定义

链接也称为超链接,所谓的超链接是指从一个网页指向一个目标的连接关系,这个目标可以是另一个网页,也可以是相同网页上的不同位置,还可以是一个图片,一个电子邮件地址,一个文件,甚至是一个应用程序。而在一个网页中用来超链接的对象,可以是一段文本或者是一个图片。当浏览者单击已经链接的文字或图片后,链接目标将显示在浏览器上,并且根据目标的类型来打开或运行。

样式

链接可以是一个字或是一段字这样的文本,也可以是一个按钮,一张图片,当你点击后跳转到另一个目标,当你把鼠标指针移到某个链接时会变成一个小手,当然在手机上没有这一特点。

1. 文本样式的链接

文本样式的链接一般在搜索引擎的网站呈现蓝色字样,大多会在下面加上下划线以便识别,不过现如今考虑到不影响文本的可读性与用户体验,逐渐取消了下划线。而在一些别的网站考虑到界面设计风格各方面的因素而不用蓝色。

谷歌的文本链接是蓝色,没有下划线

百度的文本链接也是蓝色,关键词是红色,有下划线

而京东的文本链接有灰色,有白色,有黑色

2. 按钮样式的链接

按钮样式的链接比文本样式的更容易识别,每一个按钮都是一样链接。

按钮样式链接

3. 图片样式的链接

图片样式的链接可以是单独的一张图片,也可以是文字与按钮一起组成一张图片,只是鼠标指针扫过图片的任何一个部位都会变成小手。

如桌面弹出这种游戏小窗口的图片式链接

由文字/图/按钮样式一起构成的一张图片式按钮,鼠标可以点击图中任何一部位

打开方式

链接打开的方式有三种:第一种是在当前页面刷新跳转,国外的网站大多是这样的打开式;第二种是在新标签页面打开链接,国内大多采用这种;第三种是提示用APP打开。当然现在出现了一种新的打开方式,那就是二维码扫描。

提示用美拍APP打开

类型

按照连接路径的不同,网页中超链接一般分为以下3种类型:内部链接,锚点链接和外部链接。

链接还可以分为动态链接和静态链接。动态超链接指的是可以通过改变HTML代码来实现动态变化的链接,例如我们可以实现将鼠标移动到某个文字链接上,文字就会象动画一样动起来或改变颜色的效果,也可以实现鼠标移到图片上图片就产生反色或朦胧等等的效果。而静态链接,顾名思义,就是没有动态效果的链接。

1. 内部链接

与外部链接(即反向链接)相反,内部链接是指同一网站域名下的内容页面之间互相链接。如频道、栏目、终极内容页之间的链接,乃至站内关键词之间的Tag链接都可以归类为内部链接,因此内部链接我们也可以称之为站内链接,对内部链接的优化其实就是对网站的站内链接的优化。

2. 锚点链接

HTML中的链接,正确的说法应该称作"锚点",它命名锚点链接(也叫书签链接)常常用于那些内容庞大繁琐的网页,通过点击命名锚点,不仅让我们能指向文档,还能指向页面里的特定段落,更能当作"精准链接"的便利工具,让链接对象接近焦点。便于浏览者查看网页内容。类似于我们阅读书籍时的目录页码或章回提示。在需要指定到页面的特定部分时,标记锚点是最佳的方法。

3. 外部链接

外部链接,又常被称为:“反向链接”或“导入链接”,是指通过其他网站链接到你的网站的链接。

外部链接指的是针对搜索引擎,与其它站点所做的友情链接。高质量的外部链接指:和你的网站建立链接的网站知名度高,访问量大,同时相对的外部链接较少,有助于快速提升你的网站知名度和排名的其他网站的友情链接。

如果按照使用对象的不同,网页中的链接又可以分为:文本超链接,图像超链接,E-mail链接,锚点链接,多媒体文件链接,空链接等。

链接是一种对象,它以特殊编码的文本或图形的形式来实现链接,如果单击该链接,则相当于指示浏览器移至同一网页内的某个位置,或打开一个新的网页,或打开某一个新的WWW网站中的网页。

链接状态

链接在交互上一般会呈现4种状态,即默认状态/悬停时状态/点击时状态/点击后状态。比如谷哥网站的交互体验。如下图:

点击前

悬停时,下面浮现半透明线条

点击时,有波纹晕开的动态效果

点击后,下面线条粗

有时候是3种状态,比如百度网和知乎应用:

默认状态

点击时链接变红

点击后链接变成紫色

IOS系统知乎应用的3种状态,而在Android系统没有用力点击这一状态。

默认状态

点击状态

用力点击会弹出预览小窗口

有些时候只有2种状态,如下图谷歌网:

默认和点击后状态一样

鼠标悬停时出现下划线

默认状态

点击时

而有时候比如在APP里有时候就一直只有一种状态,也可以称静态链接,之前的可以称之为动态链接。在不同的使用场景会因为当时的情况选择最合适的交互体验设计。有的情况下还会加上点击的音效,使用户体验更畅快,这在移动端用的使用情况多一些。

总之链接是网页不可缺少的构成部分,每一个链接的呈现都是经过深思熟虑的。

作者:潘瑶琼(简书作者)

本文由 @潘瑶琼 授权发布于人人都是产品经理,未经作者许可,禁止转载。