构建 Python 相机 SDK 并使用它进行多条码扫描

现在,轻量级 c 相机 sdk 已针对 windowslinuxmacos 完成,我们可以将其集成到其他高级编程语言中。在本文中,我们将探讨如何基于 c 相机库构建 python 相机 sdk,并使用它与 dynamsoft barcode reader sdk 进行多条码扫描。

python 多条码扫描仪演示视频

搭建 cpython 扩展项目的脚手架

cpython 扩展是一个共享库(例如,windows 上的 dll、linux 上的 .so 或 macos 上的 .dylib)可以在运行时加载到python解释器中并用于扩展其功能。 lite相机cpython扩展项目的结构如下:

python-lite-camera││── include│   ├── camera.h│   ├── camerapreview.h│   ├── stb_image_write.h│── lib│   ├── linux│   │   ├── liblitecam.so│   ├── macos│   │   ├── liblitecam.dylib│   ├── windows│   │   ├── litecam.dll│   │   ├── litecam.lib├── src│   ├── litecam.cpp│   ├── pycamera.h│   ├── pywindow.h│── litecam│   ├── __init__.py│── setup.py│── manifest.in│── readme.md

说明

include:c 相机库的头文件。lib:c 相机库的共享库。src:python相机sdk的源代码。litecam:python 扩展的入口点。setup.py:构建脚本。manifest.in:包含非python文件的清单文件。readme.md:文档。

为 python 扩展编写构建脚本 setup.py

在setup.py中添加以下内容:

from setuptools.command import build_extfrom setuptools import setup, extensionimport sysimport osimport iofrom setuptools.command.install import installimport shutilfrom pathlib import pathlib_dir = ''sources = [    "src/litecam.cpp",]include_dirs = [os.path.join(os.path.dirname(__file__), "include")]libraries = ['litecam']extra_compile_args = []if sys.platform == "linux" or sys.platform == "linux2":    lib_dir = 'lib/linux'    extra_compile_args = ['-std=c++11']    extra_link_args = ["-wl,-rpath=$origin"]elif sys.platform == "darwin":    lib_dir = 'lib/macos'    extra_compile_args = ['-std=c++11']    extra_link_args = ["-wl,-rpath,@loader_path"]elif sys.platform == "win32":    lib_dir = 'lib/windows'    extra_link_args = []else:    raise runtimeerror("unsupported platform")long_description = io.open("readme.md", encoding="utf-8").read()module_litecam = extension(    "litecam",    sources=sources,    include_dirs=include_dirs,    library_dirs=[lib_dir],    libraries=libraries,    extra_compile_args=extra_compile_args,    extra_link_args=extra_link_args,)def copyfiles(src, dst):    if os.path.isdir(src):        filelist = os.listdir(src)        for file in filelist:            libpath = os.path.join(src, file)            shutil.copy2(libpath, dst)    else:        shutil.copy2(src, dst)class custombuildext(build_ext.build_ext):    def run(self):        build_ext.build_ext.run(self)        dst = os.path.join(self.build_lib, "litecam")        copyfiles(lib_dir, dst)        filelist = os.listdir(self.build_lib)        for file in filelist:            filepath = os.path.join(self.build_lib, file)            if not os.path.isdir(file):                copyfiles(filepath, dst)                os.remove(filepath)class custombuildextdev(build_ext.build_ext):    def run(self):        build_ext.build_ext.run(self)        dev_folder = os.path.join(path(__file__).parent, 'litecam')        copyfiles(lib_dir, dev_folder)        filelist = os.listdir(self.build_lib)        for file in filelist:            filepath = os.path.join(self.build_lib, file)            if not os.path.isdir(file):                copyfiles(filepath, dev_folder)class custominstall(install):    def run(self):        install.run(self)setup(name='lite-camera',      version='2.0.1',      description='litecam is a lightweight, cross-platform library for capturing rgb frames from cameras and displaying them. designed with simplicity and ease of integration in mind, litecam supports windows, linux and macos platforms.',      long_description=long_description,      long_description_content_type="text/markdown",      author='yushulx',      url='https://github.com/yushulx/python-lite-camera',      license='mit',      packages=['litecam'],      ext_modules=[module_litecam],      classifiers=[           "development status :: 5 - production/stable",           "environment :: console",           "intended audience :: developers",          "intended audience :: education",          "intended audience :: information technology",          "intended audience :: science/research",          "license :: osi approved :: mit license",          "operating system :: microsoft :: windows",          "operating system :: macos",          "operating system :: posix :: linux",          "programming language :: python",          "programming language :: python :: 3",          "programming language :: python :: 3 :: only",          "programming language :: python :: 3.6",          "programming language :: python :: 3.7",          "programming language :: python :: 3.8",          "programming language :: python :: 3.9",          "programming language :: python :: 3.10",          "programming language :: python :: 3.11",          "programming language :: python :: 3.12",          "programming language :: c++",          "programming language :: python :: implementation :: cpython",          "topic :: scientific/engineering",          "topic :: software development",      ],      cmdclass={          'install': custominstall,          'build_ext': custombuildext,          'develop': custombuildextdev},      )

说明

lite-camera:python 包的名称。ext_modules:cpython 扩展列表。它指定不同平台的源文件、包含目录、库目录、库以及编译/链接标志。开发:用于开发的自定义命令。它将共享库复制到 litecam 文件夹以方便测试。build_ext:自定义构建过程,将共享库打包到wheel包中。

用 c 实现 python camera sdk api

pycamera.h 文件定义了用于从相机捕获帧的 pycamera python 类,而 pywindow.h 文件定义了用于在窗口中显示帧的 pywindow python 类。 litecam.cpp 文件作为 python 扩展的入口点,其中定义了一些全局方法,并注册了 pycamera 和 pywindow 类。

pycamera.h

包括

#include #include #include "camera.h"

python.h:包含使用 python c api。structmember.h:提供用于管理对象成员的宏和帮助器。camera.h:定义 camera 类,pycamera 扩展对其进行包装。

pycamera 结构体定义

typedef struct{    pyobject_head camera *handler;} pycamera;

pycamera 结构体表示包装 c camera 对象的 python 对象。该处理程序是一个指向 camera 类实例的指针。

立即学习“Python免费学习笔记(深入)”;

方法

pycamera_dealloc

8556677774455

解除分配 camera 对象并释放关联的内存。

pycamera_new

static pyobject *pycamera_new(pytypeobject *type, pyobject *args, pyobject *kwds){    pycamera *self;    self = (pycamera *)type->tp_alloc(type, 0);    if (self != null)    {        self->handler = new camera();    }    return (pyobject *)self;}

创建 pycamera 的新实例。它为python对象分配内存,创建一个新的camera对象,并将其分配给self->handler。

开放

static pyobject *open(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    int index = 0;    if (!pyarg_parsetuple(args, "i", &index))    {        return null;    }    bool ret = self->handler->open(index);    return py_buildvalue("i", ret);}

打开指定索引的相机。

列表媒体类型

static pyobject *listmediatypes(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    std::vector mediatypes = self->handler->listsupportedmediatypes();    pyobject *pylist = pylist_new(0);    for (size_t i = 0; i < mediatypes.size(); i++)    {        mediatypeinfo &mediatype = mediatypes[i];#ifdef _win32        pyobject *subtypename = pyunicode_fromwidechar(mediatype.subtypename, wcslen(mediatype.subtypename));        pyobject *pymediatype = py_buildvalue("{s:i,s:i,s:o}",                                              "width", mediatype.width,                                              "height", mediatype.height,                                              "subtypename", subtypename);        if (subtypename != null)        {            py_decref(subtypename);        }#else        pyobject *pymediatype = py_buildvalue("{s:i,s:i,s:s}",                                              "width", mediatype.width,                                              "height", mediatype.height,                                              "subtypename", mediatype.subtypename);#endif        pylist_append(pylist, pymediatype);    }    return pylist;}

返回支持的媒体类型列表。对于 windows,它将宽字符串转换为 python unicode 对象。

发布

static pyobject *release(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    self->handler->release();    py_return_none;}

释放相机。

设置分辨率

static pyobject *setresolution(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    int width = 0, height = 0;    if (!pyarg_parsetuple(args, "ii", &width, &height))    {        return null;    }    int ret = self->handler->setresolution(width, height);    return py_buildvalue("i", ret);}

设置相机的分辨率。

捕获帧

static pyobject *captureframe(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    framedata frame = self->handler->captureframe();    if (frame.rgbdata)    {        pyobject *rgbdata = pybytearray_fromstringandsize((const char *)frame.rgbdata, frame.size);        pyobject *pyframe = py_buildvalue("iiio", frame.width, frame.height, frame.size, rgbdata);        releaseframe(frame);        return pyframe;    }    else    {        py_return_none;    }}

从相机捕获帧并将 rgb 数据作为 python 字节数组返回。

getwidth 和 getheight

static pyobject *getwidth(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    int width = self->handler->framewidth;    return py_buildvalue("i", width);}static pyobject *getheight(pyobject *obj, pyobject *args){    pycamera *self = (pycamera *)obj;    int height = self->handler->frameheight;    return py_buildvalue("i", height);}

返回捕获帧的宽度和高度。

实例方法

static pymethoddef instance_methods[] = {    {"open", open, meth_varargs, null},    {"listmediatypes", listmediatypes, meth_varargs, null},    {"release", release, meth_varargs, null},    {"setresolution", setresolution, meth_varargs, null},    {"captureframe", captureframe, meth_varargs, null},    {"getwidth", getwidth, meth_varargs, null},    {"getheight", getheight, meth_varargs, null},    {null, null, 0, null}};

定义 pycamera python 对象上可用的方法。这些方法与上面定义的相应 c 函数相关联。

pycamera类型

static pytypeobject pycameratype = {    pyvarobject_head_init(null, 0) "litecam.pycamera", /* tp_name */    sizeof(pycamera),                                  /* tp_basicsize */    0,                                                 /* tp_itemsize */    (destructor)pycamera_dealloc,                      /* tp_dealloc */    0,                                                 /* tp_print */    0,                                                 /* tp_getattr */    0,                                                 /* tp_setattr */    0,                                                 /* tp_reserved */    0,                                                 /* tp_repr */    0,                                                 /* tp_as_number */    0,                                                 /* tp_as_sequence */    0,                                                 /* tp_as_mapping */    0,                                                 /* tp_hash  */    0,                                                 /* tp_call */    0,                                                 /* tp_str */    pyobject_genericgetattr,                           /* tp_getattro */    pyobject_genericsetattr,                           /* tp_setattro */    0,                                                 /* tp_as_buffer */    py_tpflags_default | py_tpflags_basetype,          /*tp_flags*/    "pycamera",                                        /* tp_doc */    0,                                                 /* tp_traverse */    0,                                                 /* tp_clear */    0,                                                 /* tp_richcompare */    0,                                                 /* tp_weaklistoffset */    0,                                                 /* tp_iter */    0,                                                 /* tp_iternext */    instance_methods,                                  /* tp_methods */    0,                                                 /* tp_members */    0,                                                 /* tp_getset */    0,                                                 /* tp_base */    0,                                                 /* tp_dict */    0,                                                 /* tp_descr_get */    0,                                                 /* tp_descr_set */    0,                                                 /* tp_dictoffset */    0,                                                 /* tp_init */    0,                                                 /* tp_alloc */    pycamera_new,                                      /* tp_new */};

定义 pycamera 类型,包括其方法、内存分配、释放和其他行为。

pywindow.h

包括

#include #include #include "camerapreview.h"

python.h:使用 python c api 所需的。structmember.h:提供管理对象成员的宏。camerapreview.h:定义camerawindow类,用于显示相机预览并与其交互。

pywindow 结构体定义

typedef struct{    pyobject_head camerawindow *handler;} pywindow;

定义一个包装 c camerawindow 对象的 pywindow 结构体。 handler 成员指向 camerawindow 的一个实例。

pywindow 对象的方法

pywindow_dealloc

static int pywindow_clear(pywindow *self){    if (self->handler)    {        delete self->handler;    }    return 0;}static void pywindow_dealloc(pywindow *self){    pywindow_clear(self);    py_type(self)->tp_free((pyobject *)self);}

取消分配camerawindow对象并释放内存。

pywindow_new

static pyobject *pywindow_new(pytypeobject *type, pyobject *args, pyobject *kwds){    pywindow *self;    int width = 0, height = 0;    char *title = null;    if (!pyarg_parsetuple(args, "iis", &width, &height, &title))    {        return null;    }    self = (pywindow *)type->tp_alloc(type, 0);    if (self != null)    {        self->handler = new camerawindow(width, height, title);        if (!self->handler->create())        {            std::cerr << "failed to create window." <handler->show();    }    return (pyobject *)self;}

创建 pywindow 的新实例。它为python对象分配内存,创建一个新的camerawindow对象,并将其分配给self->handler。

等待键

static pyobject *waitkey(pyobject *obj, pyobject *args){    pywindow *self = (pywindow *)obj;    const char *key = null;    if (!pyarg_parsetuple(args, "s", &key) || strlen(key) != 1)    {        pyerr_setstring(pyexc_valueerror, "expected a single character string");        return null;    }    bool ret = self->handler->waitkey(key[0]);    return py_buildvalue("i", ret);}

等待按键事件,如果按键与指定字符匹配则返回 false。 false 意味着应用程序应该退出。

showframe

static pyobject *showframe(pyobject *obj, pyobject *args){    pywindow *self = (pywindow *)obj;    int width = 0, height = 0;    pyobject *bytearray = null;    if (!pyarg_parsetuple(args, "iio", &width, &height, &bytearray))    {        return null;    }    unsigned char *data = (unsigned char *)pybytearray_asstring(bytearray);    self->handler->showframe(data, width, height);    py_return_none;}

在窗口中显示一个框架。

绘制轮廓

static pyobject *drawcontour(pyobject *obj, pyobject *args){    pywindow *self = (pywindow *)obj;    pyobject *pypoints = null;    if (!pyarg_parsetuple(args, "o", &pypoints))    {        return null;    }    std::vector<std::pair> points;    for (py_ssize_t i = 0; i handler->drawcontour(points);    py_return_none;}

在框架上绘制轮廓(一系列点)。

绘制文本

static pyobject *drawtext(pyobject *obj, pyobject *args){    pywindow *self = (pywindow *)obj;    const char *text = null;    int x = 0, y = 0, fontsize = 0;    pyobject *pycolor = null;    if (!pyarg_parsetuple(args, "siiio", &text, &x, &y, &fontsize, &pycolor))    {        return null;    }    camerawindow::color color;    color.r = (unsigned char)pylong_aslong(pytuple_getitem(pycolor, 0));    color.g = (unsigned char)pylong_aslong(pytuple_getitem(pycolor, 1));    color.b = (unsigned char)pylong_aslong(pytuple_getitem(pycolor, 2));    self->handler->drawtext(text, x, y, fontsize, color);    py_return_none;}

在框架上绘制文本。

窗口实例方法

static pymethoddef window_instance_methods[] = {    {"waitkey", waitkey, meth_varargs, null},    {"showframe", showframe, meth_varargs, null},    {"drawcontour", drawcontour, meth_varargs, null},    {"drawtext", drawtext, meth_varargs, null},    {null, null, 0, null}};

定义 pywindow python 对象上可用的方法。

pywindow类型

static pytypeobject pywindowtype = {    pyvarobject_head_init(null, 0) "litecam.pywindow", /* tp_name */    sizeof(pywindow),                                  /* tp_basicsize */    0,                                                 /* tp_itemsize */    (destructor)pywindow_dealloc,                      /* tp_dealloc */    0,                                                 /* tp_print */    0,                                                 /* tp_getattr */    0,                                                 /* tp_setattr */    0,                                                 /* tp_reserved */    0,                                                 /* tp_repr */    0,                                                 /* tp_as_number */    0,                                                 /* tp_as_sequence */    0,                                                 /* tp_as_mapping */    0,                                                 /* tp_hash  */    0,                                                 /* tp_call */    0,                                                 /* tp_str */    pyobject_genericgetattr,                           /* tp_getattro */    pyobject_genericsetattr,                           /* tp_setattro */    0,                                                 /* tp_as_buffer */    py_tpflags_default | py_tpflags_basetype,          /*tp_flags*/    "pywindow",                                        /* tp_doc */    0,                                                 /* tp_traverse */    0,                                                 /* tp_clear */    0,                                                 /* tp_richcompare */    0,                                                 /* tp_weaklistoffset */    0,                                                 /* tp_iter */    0,                                                 /* tp_iternext */    window_instance_methods,                           /* tp_methods */    0,                                                 /* tp_members */    0,                                                 /* tp_getset */    0,                                                 /* tp_base */    0,                                                 /* tp_dict */    0,                                                 /* tp_descr_get */    0,                                                 /* tp_descr_set */    0,                                                 /* tp_dictoffset */    0,                                                 /* tp_init */    0,                                                 /* tp_alloc */    pywindow_new,                                      /* tp_new */};

定义 pywindow 类型,包括其方法、内存分配、释放和其他行为。

litecam.cpp

#include #include #include "pycamera.h"#include "pywindow.h"#define initerror return nullstatic pyobject *getdevicelist(pyobject *obj, pyobject *args){    pyobject *pylist = pylist_new(0);    std::vector devices = listcapturedevices();    for (size_t i = 0; i < devices.size(); i++)    {        capturedeviceinfo &device = devices[i];#ifdef _win32        pyobject *pyname = pyunicode_fromwidechar(device.friendlyname, wcslen(device.friendlyname));        if (pyname != null)        {            pylist_append(pylist, pyname);            py_decref(pyname);        }#else        pyobject *pyname = pyunicode_fromstring(device.friendlyname);        if (pyname != null)        {            pylist_append(pylist, pyname);            py_decref(pyname);        }#endif    }    return pylist;}static pyobject *savejpeg(pyobject *obj, pyobject *args){    const char *filename = null;    int width = 0, height = 0;    pyobject *bytearray = null;    if (!pyarg_parsetuple(args, "siio", &filename, &width, &height, &bytearray))    {        pyerr_setstring(pyexc_typeerror, "expected arguments: str, int, int, pybytearray");        return null;    }    unsigned char *data = (unsigned char *)pybytearray_asstring(bytearray);    py_ssize_t size = pybytearray_size(bytearray);    if (size != (py_ssize_t)(width * height * 3))    {        pyerr_setstring(pyexc_valueerror, "invalid byte array size for the given width and height.");        return null;    }    saveframeasjpeg(data, width, height, filename);    py_return_none;}static pymethoddef litecam_methods[] = {    {"getdevicelist", getdevicelist, meth_varargs, "get available cameras"},    {"savejpeg", savejpeg, meth_varargs, "get available cameras"},    {null, null, 0, null}};static struct pymoduledef litecam_module_def = {    pymoduledef_head_init,    "litecam",    "internal "litecam" module",    -1,    litecam_methods};pymodinit_func pyinit_litecam(void){    pyobject *module = pymodule_create(&litecam_module_def);    if (module == null)        initerror;    if (pytype_ready(&pycameratype) < 0)    {        printf("failed to initialize pycameratypen");        py_decref(module);        return null;    }    if (pymodule_addobject(module, "pycamera", (pyobject *)&pycameratype) < 0)    {        printf("failed to add pycamera to the modulen");        py_decref(&pycameratype);        py_decref(module);        initerror;    }    if (pytype_ready(&pywindowtype) < 0)    {        printf("failed to initialize pywindowtypen");        py_decref(module);        return null;    }    if (pymodule_addobject(module, "pywindow", (pyobject *)&pywindowtype) < 0)    {        printf("failed to add pywindow to the modulen");        py_decref(&pywindowtype);        py_decref(module);        initerror;    }    return module;}

说明

getdevicelist:返回可用摄像头的列表。savejpeg:将帧保存为 jpeg 图像。pyinit_litecam:初始化litecam模块并注册pycamera和pywindow类型。

构建 python 相机 sdk

开发模式

python setup.py develop

轮组

python setup.py bdist_wheel

来源分布

python setup.py sdist

实现 python 多条码扫描器的步骤

安装python相机sdk和dynamsoft barcode reader sdk:

pip install lite-camera dynamsoft-capture-vision-bundle

获取 dynamsoft barcode reader 30 天免费试用许可证。

创建用于多条码扫描的 python 脚本:

import litecamfrom dynamsoft_capture_vision_bundle import *import queueclass framefetcher(imagesourceadapter):    def has_next_image_to_fetch(self) -> bool:        return true    def add_frame(self, imagedata):        self.add_image_to_buffer(imagedata)class mycapturedresultreceiver(capturedresultreceiver):    def __init__(self, result_queue):        super().__init__()        self.result_queue = result_queue    def on_captured_result_received(self, captured_result):        self.result_queue.put(captured_result)if __name__ == '__main__':    errorcode, errormsg = licensemanager.init_license(        "license-key")    if errorcode != enumerrorcode.ec_ok and errorcode != enumerrorcode.ec_license_cache_used:        print("license initialization failed: errorcode:",              errorcode, ", errorstring:", errormsg)    else:        camera = litecam.pycamera()        if camera.open(0):            cvr = capturevisionrouter()            fetcher = framefetcher()            cvr.set_input(fetcher)            result_queue = queue.queue()            receiver = mycapturedresultreceiver(result_queue)            cvr.add_result_receiver(receiver)            errorcode, errormsg = cvr.start_capturing(                enumpresettemplate.pt_read_barcodes.value)            if errorcode != enumerrorcode.ec_ok:                print("error:", errormsg)            window = litecam.pywindow(                camera.getwidth(), camera.getheight(), "camera stream")            while window.waitkey('q'):                frame = camera.captureframe()                if frame is not none:                    width = frame[0]                    height = frame[1]                    size = frame[2]                    data = frame[3]                    window.showframe(width, height, data)                    imagedata = imagedata(                        bytes(data), width, height, width * 3, enumimagepixelformat.ipf_rgb_888)                    fetcher.add_frame(imagedata)                    if not result_queue.empty():                        captured_result = result_queue.get_nowait()                        items = captured_result.get_items()                        for item in items:                            if item.get_type() == enumcapturedresultitemtype.crit_barcode:                                text = item.get_text()                                location = item.get_location()                                x1 = location.points[0].x                                y1 = location.points[0].y                                x2 = location.points[1].x                                y2 = location.points[1].y                                x3 = location.points[2].x                                y3 = location.points[2].y                                x4 = location.points[3].x                                y4 = location.points[3].y                                contour_points = [                                    (x1, y1), (x2, y2), (x3, y3), (x4, y4)]                                window.drawcontour(contour_points)                                window.drawtext(text, x1, y1, 24, (255, 0, 0))                                del location            camera.release()            cvr.stop_capturing()

将 license-key 替换为您的 dynamsoft barcode reader 许可证密钥。

运行脚本:

python main.py

python multi-barcode scanner

源代码

https://github.com/yushulx/python-lite-camera

以上就是构建 Python 相机 SDK 并使用它进行多条码扫描的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1355262.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月13日 19:08:06
下一篇 2025年12月13日 19:08:19

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 旋转长方形后,如何计算其相对于画布左上角的轴距?

    绘制长方形并旋转,计算旋转后轴距 在拥有 1920×1080 画布中,放置一个宽高为 200×20 的长方形,其坐标位于 (100, 100)。当以任意角度旋转长方形时,如何计算它相对于画布左上角的 x、y 轴距? 以下代码提供了一个计算旋转后长方形轴距的解决方案: const x = 200;co…

    2025年12月24日
    000
  • 旋转长方形后,如何计算它与画布左上角的xy轴距?

    旋转后长方形在画布上的xy轴距计算 在画布中添加一个长方形,并将其旋转任意角度,如何计算旋转后的长方形与画布左上角之间的xy轴距? 问题分解: 要计算旋转后长方形的xy轴距,需要考虑旋转对长方形宽高和位置的影响。首先,旋转会改变长方形的长和宽,其次,旋转会改变长方形的中心点位置。 求解方法: 计算旋…

    2025年12月24日
    000
  • 旋转长方形后如何计算其在画布上的轴距?

    旋转长方形后计算轴距 假设长方形的宽、高分别为 200 和 20,初始坐标为 (100, 100),我们将它旋转一个任意角度。根据旋转矩阵公式,旋转后的新坐标 (x’, y’) 可以通过以下公式计算: x’ = x * cos(θ) – y * sin(θ)y’ = x * …

    2025年12月24日
    000
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 如何计算旋转后长方形在画布上的轴距?

    旋转后长方形与画布轴距计算 在给定的画布中,有一个长方形,在随机旋转一定角度后,如何计算其在画布上的轴距,即距离左上角的距离? 以下提供一种计算长方形相对于画布左上角的新轴距的方法: const x = 200; // 初始 x 坐标const y = 90; // 初始 y 坐标const w =…

    2025年12月24日
    200
  • CSS元素设置em和transition后,为何载入页面无放大效果?

    css元素设置em和transition后,为何载入无放大效果 很多开发者在设置了em和transition后,却发现元素载入页面时无放大效果。本文将解答这一问题。 原问题:在视频演示中,将元素设置如下,载入页面会有放大效果。然而,在个人尝试中,并未出现该效果。这是由于macos和windows系统…

    2025年12月24日
    200
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 如何用HTML/JS实现Windows 10设置界面鼠标移动探照灯效果?

    Win10设置界面中的鼠标移动探照灯效果实现指南 想要在前端开发中实现类似于Windows 10设置界面的鼠标移动探照灯效果,有两种解决方案:CSS 和 HTML/JS 组合。 CSS 实现 不幸的是,仅使用CSS无法完全实现该效果。 立即学习“前端免费学习笔记(深入)”; HTML/JS 实现 要…

    2025年12月24日
    000
  • 如何计算旋转后的长方形在画布上的 XY 轴距?

    旋转长方形后计算其画布xy轴距 在创建的画布上添加了一个长方形,并提供其宽、高和初始坐标。为了视觉化旋转效果,还提供了一些旋转特定角度后的图片。 问题是如何计算任意角度旋转后,这个长方形的xy轴距。这涉及到使用三角学来计算旋转后的坐标。 以下是一个 javascript 代码示例,用于计算旋转后长方…

    2025年12月24日
    000
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000

发表回复

登录后才能评论
关注微信