无论我们尝试使 Web 应用程序多么简单,引导新用户完成第一次体验通常都是有帮助的。视觉游览可能是最简单的方法。
如果您关注过我的 Envato Tuts+ 使用 PHP 创建您的初创公司系列,那么您就会熟悉会议规划器。在观察用户安排第一次会议后,我决定最好构建某种指南。
起初,我考虑自己构建它,但后来我找到了一个开源选项,Shepherd。
在今天的教程中,我将向您介绍如何使用 Shepherd 构建可视化用户之旅。使用 Shepherd 相对简单,我将回顾一些我自己用来简化创作过程的代码。
Shepherd 是 HubSpot(一项入站营销服务)的开源产品。感谢他们提供了一个强大的库和良好的文档。
Shepherd 的工作原理
让我们看一下 Shepherd 的一个简单场景。
使用 Shepherd 将基本浏览集成到您的应用程序中非常简单。首先,您选择一个主题文件并集成其 JavaScript,如下所示:
登录后复制
您可以从 Shepherd GitHub 页面下载文件。我使用上面的 shepherd-theme-arrows.css
,但您可以从下面的任何默认值中进行选择并自定义它们:
接下来,您创建一个游览对象:
const tour = new Shepherd.Tour({
defaultStepOptions: {
classes: 'shepherd-theme-arrows',
scrollTo: true
}
});
登录后复制
使用 defaultStepOptions
键创建游览时,可以为所有步骤定义默认值。 classes
指的是您使用的主题定义,例如shepherd-theme-arrows
和 scrollTo
有助于在 scrollIntoView()
方法的帮助下确保所有步骤都出现在可见视口中。
然后,您可以向游览添加单独的步骤:
tour.addStep('example-step', {
text: 'This step is attached to the bottom of the .
element.',
example-css-selector
attachTo: { element: '.example-css-selector', on: 'bottom'},
classes: 'example-step-extra-class',
buttons: [
{
text: 'Next',
action: tour.next
}
]
});
登录后复制
text
是出现在视觉之旅正文中的内容。文本可以是常规 HTML 字符串,也可以是 HTMLElement
对象。您还可以在此处提供一个回调函数,该函数将在构建步骤时执行。但是,它必须返回 HTML 字符串或 HTMLElement
对象。
attachTo
关键点指向要附加此步骤的项目的 CSS 选择器。它期望一个对象作为其值。
buttons
键允许您定义一个或多个按钮及其操作,例如。 Next
.该键接受按钮对象数组作为其值。按钮对象将具有控制按钮行为和外观的键值对。
最后,您开始游览:
tour.start();
登录后复制
Shepherd 构建于 Tether(另一个 HubSpot 开源产品)之上,它有助于将元素定位到页面上的其他元素。 Tether 确保您的步数不会溢出屏幕或被裁剪。
将 Tether 集成到您自己的应用程序中
当我开始尝试 Shepherd 时,我很快发现编写包含许多步骤的指南可能会相当冗长。这是我在自己的实现中解决的问题。
我不想使用大量需要长期维护的 JavaScript 代码来编写游览。相反,我选择创建一个数组,并根据用户是在游览的开始还是结束时以编程方式自定义按钮。
例如,我创建一个 steps[]
数组并通过填充该数组来定义游览:
const tour = new Shepherd.Tour({
defaultStepOptions: {
classes: 'shepherd-theme-arrows',
scrollTo: true
}
});
const steps = [];
steps.push({
attachTo: {
element: '.nav-tabs',
on: 'top'
},
title: 'Welcome',
text: `Allow me to show you how to plan a ${title}.
If you prefer, you can turn off this guide.`
});
steps.push({
attachTo: {
element: '#headingWho',
on: 'top'
},
title: 'Who would you like to invite?',
text: `You can add one person or a group of people to your ${title}.
Click the person button to add participants.
`
});
steps.push({
attachTo: {
element: '#invitation-url',
on: 'bottom'
},
title: 'Inviting by email',
text: 'Alternately, you can email the meeting link to your participant(s)'
});
steps.push({
attachTo: {
element: '#headingWhat',
on: 'bottom'
},
title: 'What is your meeting about?',
text: `You can customize the subject of your ${title}. We'll use it for the invitation and reminder emails.
Click the pencil button to edit the subject.
`
});
if ($('#headingActivity').length > 0) {
steps.push({
attachTo: {
element: '#headingActivity',
on: 'top'
},
title: 'What do you want to do?',
text: 'You can suggest one or more activity ideas. With multiple ideas, your participants can help you select their favorite.
Click the plus button to suggest activities.
'
});
}
steps.push({
attachTo: {
element: '#headingWhen',
on: 'top'
},
title: 'When do you want to meet?',
text: `Suggest one or more dates and times for your ${title}. With more than one, your participants can help you choose.
Click the + button to add them.
`
});
steps.push({
attachTo: {
element: '#headingWhere',
on: 'top'
},
title: 'Where do you want to meet?',
text: `Suggest one or more places for your ${title}. With multiple places, your participants can help you choose.
We use Google Places to simplify adding them. Click the + button to begin.
`
});
steps.push({
attachTo: {
element: '.virtualThing',
on: 'top'
},
title: 'Is this a virtual meeting?',
text: `Switch between in person and virtual ${title}s such as phone calls or online conferences.`
});
steps.push({
attachTo: {
element: '#actionSend',
on: 'top'
},
title: 'Sending invitations',
text: `Scheduling is collaborative. After you add times and places, you can Invite participants to select their favorites. A place isn't necessary for virtual ${title}s.`
});
steps.push({
attachTo: {
element: '#actionFinalize',
on: 'right'
},
title: 'Finalizing the plan',
text: `Once you choose a time and place, you can Complete the plan. We'll email the invitations and setup reminders.`
});
steps.push({
attachTo: {
element: '#tourDiscussion',
on: 'left'
},
title: 'Share messages with participants',
text: 'You can write back and forth with participants on the Messages tab.
Messages are delivered via email.
'
});
steps.push({
attachTo: {
element: '.container',
on: 'top'
},
title: 'Ask a question',
text: `Need help? Ask a question and we'll respond as quickly as we can.
If you prefer, you can turn off the guide in settings.
`
});
登录后复制
我添加到数组中的每个对象元素都包含三个关键信息:
{element: '.nav-tabs', on:'top'}
title
键中标题的文本,例如'你想什么时候见面?'
text
键对我来说,维护这个数组比为教程的每个步骤定义按钮要简单得多。但是,这意味着我在将步骤加载到游览中时需要以编程方式定义按钮。
我编写此代码是为了正确添加和响应游览按钮。每一步,它都会创建一个 buttons
数组,否则我必须手动定义该数组:
for (let i = 0; i 0) {
buttons.push({
text: 'Back',
classes: 'shepherd-button-secondary',
action: function() {
return tour.back();
}
});
}
// no next button on last step
if (i!=(steps.length-1)) {
buttons.push({
text: 'Next',
classes: 'shepherd-button-primary',
action: function() {
return tour.next();
}
});
} else {
buttons.push({
text: 'Close',
classes: 'shepherd-button-primary',
action: function() {
return tour.hide();
}
});
}
登录后复制
例如,第一步没有后退按钮,最后一步没有下一步按钮。但最后一步确实有一个关闭按钮。
然后,我的数组中的每个步骤和每个按钮数组都会添加到游览中。
tour.addStep(`step_${i}`, {
text: steps[i].text,
title: steps[i].title,
attachTo: steps[i].attachTo,
classes: 'shepherd shepherd-open shepherd-theme-arrows shepherd-transparent-text',
buttons: buttons,
});
}
登录后复制
使用这种方法,我不必为教程的每个步骤重复重新定义相同的按钮。它还提供了一些编程能力,可以为未来动态定制游览。
使用我选择的 PHP 编程框架 Yii,我将必要的包含文件添加到我的资源文件中。这会加载到需要游览的特定页面上。就我而言,会议安排页面: