纯JS手风琴组件实现教程与代码

需积分: 5 0 下载量 147 浏览量 更新于2024-11-17 收藏 50KB ZIP 举报
资源摘要信息:"手风琴组件是网页开发中常见的一个交互组件,它允许多个面板共存,但每次只展开一个面板,当点击其他面板时,当前展开的面板会收起,而新点击的面板会展开。本案例介绍了如何使用原生JavaScript来实现一个简单的手风琴功能,无需依赖任何第三方库。通过阅读本文档,你可以学习到如何通过JavaScript操作DOM来实现高度转换,以及如何使用事件监听器来处理用户的点击事件。" 知识点详述: 1. **手风琴组件的定义和作用**: 手风琴组件在用户界面设计中扮演着重要的角色,它允许用户通过点击来展开和收起内容区域,使得页面内容更加有序。这类组件常用于节省页面空间,同时为用户提供丰富的交互体验。在网页中,手风琴经常被用于展示FAQ(常见问题解答)、教程步骤、产品详情等信息。 2. **使用原生JavaScript实现手风琴的优势**: 相比于使用第三方库,使用原生JavaScript实现手风琴组件有以下优势: - **性能**:减少了额外库的加载,提高了页面的加载速度和运行效率。 - **可控性**:完全控制实现过程,可以更加灵活地定制功能和样式。 - **兼容性**:原生JavaScript具有良好的浏览器兼容性。 3. **HTML结构的基本要求**: 实现手风琴的基本HTML结构包括一个父级容器,内含多个子容器,每个子容器代表一个可展开收起的面板。每个面板通常包含一个标题和一个内容区域。 示例代码片段: ```html <div id="accordion"> <div class="accordion-item"> <h2 class="accordion-title">标题1</h2> <div class="accordion-content"> <p>这里是内容...</p> </div> </div> <!-- 更多面板 --> </div> ``` 4. **JavaScript实现手风琴的关键技术点**: - **选择器操作**:使用`document.querySelector`或`document.querySelectorAll`选择DOM元素。 - **事件监听**:为每个标题添加`click`事件监听器,以响应用户的点击操作。 - **DOM操作**:通过修改元素的`style.height`属性或`className`来控制内容区域的显示和隐藏。 - **CSS转换**:利用CSS的`transition`属性来实现高度变化时的动画效果。 5. **CSS样式调整**: 为了使手风琴效果更佳,需要给手风琴组件设置适当的CSS样式,包括但不限于: - 设置容器的宽度和边框。 - 使用`overflow: hidden`属性隐藏超出容器高度的内容。 - 设置`transition`属性来实现高度变化的动画效果。 示例CSS代码片段: ```css .accordion-item { border: 1px solid #ccc; margin-bottom: 5px; } .accordion-title { background: #eee; padding: 10px; cursor: pointer; } .accordion-content { padding: 10px; height: 0; overflow: hidden; transition: height 0.5s ease; } ``` 6. **事件处理逻辑**: 在JavaScript中,点击事件处理函数将决定哪个面板被展开,哪个面板被收起。事件处理逻辑大致包括以下步骤: - 获取点击元素的父容器,即面板。 - 遍历所有面板,计算应该隐藏哪个面板。 - 调整被点击面板的高度,实现展开和收起的效果。 7. **构建工具的使用**: 根据描述,使用yarn来构建项目。yarn是一个由Facebook、Google、Exponent和Tilde提供的JavaScript包管理器,它允许开发者快速使用并管理代码依赖。 - `yarn build`:构建项目,这通常会将源代码编译成生产环境所需的文件。 - `yarn start`:启动开发服务器,这允许开发者在开发过程中实时查看更改的效果。 8. **项目结构和文件列表**: 根据提供的压缩包子文件的文件名称列表`accordingly2-master`,我们可以推断出,这个项目可能包含多个文件,如JavaScript源代码文件、CSS样式文件和HTML结构文件。一个典型的项目目录结构可能包括: - `src`目录,存放源代码文件。 - `dist`目录,存放构建后的文件。 - `package.json`文件,存放项目的依赖信息和脚本命令。 总结而言,本案例为开发者提供了一个关于如何使用原生JavaScript创建手风琴组件的实例,不仅涉及到前端技术的具体应用,还包括了项目构建和开发流程的介绍。通过本案例,开发者可以获得对JavaScript、HTML、CSS以及构建工具的综合运用能力,从而提高前端开发的水平。

解释如下代码:def draw_matches(img1, kp1, img2, kp2, matches, color=None): """Draws lines between matching keypoints of two images. Keypoints not in a matching pair are not drawn. Args: img1: An openCV image ndarray in a grayscale or color format. kp1: A list of cv2.KeyPoint objects for img1. img2: An openCV image ndarray of the same format and with the same element type as img1. kp2: A list of cv2.KeyPoint objects for img2. matches: A list of DMatch objects whose trainIdx attribute refers to img1 keypoints and whose queryIdx attribute refers to img2 keypoints. """ # We're drawing them side by side. Get dimensions accordingly. # Handle both color and grayscale images. if len(img1.shape) == 3: new_shape = (max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], img1.shape[2]) elif len(img1.shape) == 2: new_shape = (max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1]) new_img = np.zeros(new_shape, type(img1.flat[0])) # Place images onto the new image. new_img[0:img1.shape[0],0:img1.shape[1]] = img1 new_img[0:img2.shape[0],img1.shape[1]:img1.shape[1]+img2.shape[1]] = img2 # Draw lines between matches. Make sure to offset kp coords in second image appropriately. r = 2 thickness = 1 print(len(kp1),len(kp2), len(matches) ) if color: c = color for m in matches[0:20]: # Generate random color for RGB/BGR and grayscale images as needed. if not color: c = np.random.randint(0,256,3) if len(img1.shape) == 3 else np.random.randint(0,256) # So the keypoint locs are stored as a tuple of floats. cv2.line(), like most other things, # wants locs as a tuple of ints. c = [255,255,255] end1 = tuple(np.round(kp1[m.queryIdx].pt).astype(int)) end2 = tuple(np.round(kp2[m.trainIdx].pt).astype(int) + np.array([img1.shape[1], 0])) cv2.line(new_img, end1, end2, c, thickness) cv2.circle(new_img, end1, r, c, thickness) cv2.circle(new_img, end2, r, c, thickness) plt.figure(figsize=(15,15)) plt.imshow(new_img) plt.show()

2023-06-13 上传

请详细解释下这段代码Rect<float> FaceTracker::GetActiveBoundingRectangleOnActiveStream() const { std::vector<Rect<float>> faces = GetActiveFaceRectangles(); if (faces.empty()) { return Rect<float>(); } float min_x0 = 1.0f, min_y0 = 1.0f, max_x1 = 0.0f, max_y1 = 0.0f; for (const auto& f : faces) { min_x0 = std::min(f.left, min_x0); min_y0 = std::min(f.top, min_y0); max_x1 = std::max(f.right(), max_x1); max_y1 = std::max(f.bottom(), max_y1); } Rect<float> bounding_rect(min_x0, min_y0, max_x1 - min_x0, max_y1 - min_y0); VLOGF(2) << "Active bounding rect w.r.t active array: " << bounding_rect; // Transform the normalized rectangle in the active sensor array space to the // active stream space. const float active_array_aspect_ratio = static_cast<float>(options_.active_array_dimension.width) / static_cast<float>(options_.active_array_dimension.height); const float active_stream_aspect_ratio = static_cast<float>(options_.active_stream_dimension.width) / static_cast<float>(options_.active_stream_dimension.height); if (active_array_aspect_ratio < active_stream_aspect_ratio) { // The active stream is cropped into letterbox with smaller height than the // active sensor array. Adjust the y coordinates accordingly. const float height_ratio = active_array_aspect_ratio / active_stream_aspect_ratio; bounding_rect.height = std::min(bounding_rect.height / height_ratio, 1.0f); const float y_offset = (1.0f - height_ratio) / 2; bounding_rect.top = std::max(bounding_rect.top - y_offset, 0.0f) / height_ratio; } else { // The active stream is cropped into pillarbox with smaller width than the // active sensor array. Adjust the x coordinates accordingly. const float width_ratio = active_stream_aspect_ratio / active_array_aspect_ratio; bounding_rect.width = std::min(bounding_rect.width / width_ratio, 1.0f); const float x_offset = (1.0f - width_ratio) / 2; bounding_rect.left = std::max(bounding_rect.left - x_offset, 0.0f) / width_ratio; } VLOGF(2) << "Active bounding rect w.r.t active stream: " << bounding_rect; return bounding_rect; }

2023-06-08 上传