国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片

這篇具有很好參考價值的文章主要介紹了React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

收到這個需求的時候,我的內(nèi)心是崩潰的,腦子里已經(jīng)跑過一萬匹草泥馬,內(nèi)心想這種事為啥不交給ps去做,哪怕是手機里圖片編輯也可以做到吧,專業(yè)的事交給專業(yè)的工具去干不就好了,何必出這種XX需求。后來想想就釋然了,反正拿錢干活,干啥不是干,只要給錢,再XX的需求我也給你寫出來。廢話不多說,請看下方示例

實現(xiàn)效果:
React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片,前端問題及案例,react.js,javascript,前端,canvas
本文案例只負(fù)責(zé)下圖所示組件,上圖中的圖片列表只是為了方便展示
React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片,前端問題及案例,react.js,javascript,前端,canvas

注:本組件使用的是React + AntD,這里樣式就不過多描寫了

思路一

首先,先說一開始錯誤的思路一,給圖片添加文字信息,我一開始想到的是用canvas。先創(chuàng)建畫布,獲取要寫入文字的圖片寬高->再創(chuàng)建一個新的圖片->然后再畫布中畫出剛才創(chuàng)建的新的圖片->輸入框文字發(fā)生改變則,獲取輸入框中輸入的文字相關(guān)信息->在畫布中繪制文字->生成新的圖片渲染到頁面。
但是最后該思路以失敗告終,這條思路只適用于只添加一條文字信息的情況,添加第二條后就會出現(xiàn)添加的文字錯亂的情況,因為新增代碼后我無法保存上條圖片的情況,無法知道上條圖片的文字新增后的狀態(tài),如果是要刪除情況又當(dāng)如何,失敗代碼如下,如果只添加一條文字信息,可以用來參考,各位慢慢研究

import React from 'react'
import { Button } from 'antd'
import ParamsOptionComp from './ParamsOptionComp'

export default class MaterialEdit extends React.Component {
  canvas = document.createElement("canvas");
  image = React.createRef();

  state = {
    imgSrc: this.props.src,
    paramAttribute: [{
      content: '文字內(nèi)容',
      color: '#000000',
      size: 24,
      left: 130,
      top: 50
    }],
    srcList: {
      0: this.props.src
    }
  }

  componentDidMount() {
    this.setState({
      paramAttribute: [{
        content: '文字內(nèi)容',
        color: '#000000',
        size: 24,
        left: (this.image.current.clientWidth / 2) - 48,
        top: (this.image.current.clientHeight / 2) + 12
      }]
    }, () => {
      this.drawImage()
    })
    this.drawImage()
  }

  // 繪制圖片
  drawImage = (params, index) => {
    // 創(chuàng)建畫布
    const ctx = this.canvas.getContext("2d");
    // 獲取圖片大小
    const imageRect = this.image.current.getBoundingClientRect();

    const { width, height } = imageRect;
    this.canvas.width = width;
    this.canvas.height = height;

    // 創(chuàng)建圖片
    const image = new Image();

    // if (index) {
    //   console.log(this.state.imgSrc, 123)
    //   image.src = this.state.imgSrc;
    // } else {
      image.src = this.props.src;
    // }

    image.onload = () => {
      ctx.drawImage(image, 0, 0, width, height);
      // 繪制文字
      this.drawText(params ? params : this.state.paramAttribute[0]);
    }

  }

  // 繪制文字
  drawText = ({ content, color, size, left, top }) => {
    // console.log(content, color, size, left, top)
    const ctx = this.canvas.getContext("2d");
    ctx.font = `${size}px Arial`;
    ctx.fillStyle = color;
    ctx.fillText(content, left, top);
    this.saveImage()
  };

  // 當(dāng)文字發(fā)生變化
  onValuesChange = (changedValues, allValues) => {
    // console.log(changedValues, allValues);

    allValues.paramAttribute.forEach((item, index) => {
      // if (item && Object.keys(item).length > 0) {
        this.drawImage(item)
      // } else if (index >= 1) {
      //   this.drawImage(item, 'index')
      // }
    })
  }

  setSrcList = (index) => {
    console.log(index)
  }

  // 保存圖片
  saveImage = () => {
    const image = this.canvas.toDataURL('image/png');
    // console.log(image);
    this.setState({ imgSrc: image });
    // 根據(jù)需要,將生成的圖片顯示給用戶或保存為新的圖片文件
    // 如:window.open(image);
  };

  // 將圖片轉(zhuǎn)成二進(jìn)制格式
  base64ToBlob = (code) => {
    let parts = code.split(';base64,')
    let contentType = parts[0].split(':')[1]
    let raw = window.atob(parts[1])
    let rawLength = raw.length
    let uint8Array = new Uint8Array(rawLength)
    for (let i = 0; i < rawLength; i++) {
      uint8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uint8Array], { type: contentType })
  }

  // 下載圖片
  download = (dataUrl, fileName) => {
    let aLink = document.createElement('a')
    let blob = this.base64ToBlob(dataUrl)
    let event = document.createEvent('HTMLEvents')
    event.initEvent('click', true, true)
    aLink.download = fileName + '.' + blob.type.split('/')[1]
    aLink.href = URL.createObjectURL(blob)
    aLink.click()
  }

  render() {
    const { imgSrc } = this.state
    const { src } = this.props
    return <>
      <div style={{ textAlign: 'center', marginBottom: '30px' }}>
        <img src={imgSrc} width={300} ref={this.image} />
      </div>
      <ParamsOptionComp onValuesChange={this.onValuesChange} paramAttribute={this.state.paramAttribute} setSrcList={this.setSrcList}/>
      <Button type="primary" htmlType="submit">
        生成新的圖片
      </Button>
    </>
  }
}

思路二

同樣也是與canvas相關(guān),不過這次想到的是,將輸入的文字信息生成節(jié)點添加到頁面中的某個模塊,然后再將這個模塊輸出成canvas然后再轉(zhuǎn)化成圖片下載下來,這里會用到html2canvas這個庫,這個庫可以讓html頁面和canvas相互轉(zhuǎn)換,大致思路如下:

下載html2canvas依賴包->搭建頁面,并創(chuàng)建新增節(jié)點的區(qū)域->初始化新增第一個節(jié)點到頁面中的某個指定模塊->當(dāng)文本框發(fā)生變動,修改節(jié)點信息->實現(xiàn)節(jié)點刪除->利用html2canvas將模塊生成canvas,然后轉(zhuǎn)化成圖片

1. 下載html2canvas依賴包
npm i html2canvas
2. 搭建頁面,并且創(chuàng)建新增節(jié)點的區(qū)域

MaterialEditComp.jsx

import React, { useEffect, useRef, useState } from 'react'
import { Button } from 'antd'
import ParamsOptionComp from './ParamsOptionComp'
import html2canvas from 'html2canvas';
import './index.less'

export default function MaterialEditComp(props) {
  const { src, getNewImage } = props;
  const [imgSrc, setImgSrc] = React.useState(src);
  const contentRef = useRef(null);
  const [imageSize, setImageSize] = useState({ width: 0, height: 0 });

  const onValuesChange = (changedValues, allValues) => {}

  // 新增節(jié)點
  const AddNode = ({content, color, size, left, top }, index) => {}

  //  刪除節(jié)點
  const removeNode = (index) => {}
  
  // 將圖片轉(zhuǎn)換成二進(jìn)制形式
  const base64ToBlob = (code) => {}

  // 保存圖片
  const saveImage = async () => {}


  useEffect(() => {
  	// 坑一
    const img = new Image();
    img.src = imgSrc

    img.onload = () => {
      setImageSize({ width: img.width, height: img.height });
    };
  }, []);


  return (
    <>
      // 新增節(jié)點區(qū)域
        <div ref={contentRef} style={{
        background: `url(${imgSrc}) no-repeat`,
        backgroundSize: 'cover',
        backgroundPosition: 'center',
        width: imageSize.width + 'px',
        height: imageSize.height + 'px',
        marginBottom: '30px'
      }} className="content">
        
      </div>
      // 輸入框組件
      <ParamsOptionComp onValuesChange={onValuesChange} imageSize={imageSize} removeNode={removeNode} />
      <Button type="primary" htmlType="submit" onClick={saveImage} className='btn'>
        生成新的圖片
      </Button>
    </>
  )
}

ParamsOptionComp.jsx

import React, { useEffect, useState } from 'react'
import { Input, Form, Space, Button, InputNumber } from 'antd'
import { PlusOutlined, MinusCircleOutlined, DragOutlined } from '@ant-design/icons'

export default function ParamsOptionComp(props) {
  const { onValuesChange, imageSize, removeNode } = props
  const [count, setCount] = useState(0)
  const [form] = Form.useForm();

  // 坑一
  useEffect(() => {
    form.resetFields()
  }, [imageSize])


  return <Form form={form} name="dynamic_form_nest_item"
    // 坑一
    initialValues={{
      paramAttribute: [{
        left: imageSize.width / 2 - 48,
        top: imageSize.height / 2 - 24,
        content: '文字內(nèi)容'
      }]
    }}
    onValuesChange={onValuesChange} >

    <Form.List name="paramAttribute">
      {(fields, { add, remove, move }) => (
        <>
          {fields.map(({ key, name, ...restField }, index) => (
            <Space key={key} style={{ display: 'flex', marginBottom: 0 }} align="baseline">
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'content']}
                label="文字內(nèi)容"
                rules={[{ required: true, message: '請輸入文字內(nèi)容' }]}
              >
                <Input placeholder="文字內(nèi)容" maxLength={50} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'color']}
                label="文字顏色"
                rules={[{ required: true, message: '請輸入文字顏色' }]}
                initialValue="#000000"
              >
                <Input placeholder="文字顏色" type="color" style={{ width: '80px' }} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'size']}
                label="文字大小"
                rules={[{ required: true, message: '請輸入文字大小' }]}
                initialValue="24"
              >
                <InputNumber placeholder="文字大小" min={12} value={13} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'top']}
                label="上邊距"
                rules={[{ required: true, message: '請輸入上邊距' }]}
                initialValue={imageSize.height / 2 - 24}
              >
                <InputNumber placeholder="上邊距" value={13} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'left']}
                label="左邊距"
                rules={[{ required: true, message: '請輸入左邊距' }]}
                initialValue={imageSize.width / 2 - 48}
              >
                <InputNumber placeholder="左邊距" value={13} />
              </Form.Item>
              <MinusCircleOutlined onClick={() => {
                if (count === 0) {
                  return
                }
                remove(name)
                removeNode(index)
                setCount(count => count - 1);
              }} />
            </Space>
          ))}
          <Form.Item>
            <Button type="dashed" onClick={async () => {
              try {
                const values = await form.validateFields()
                add();
                setCount(count => count + 1);
              } catch (errorInfo) {
                return;
              }
            }} block icon={<PlusOutlined />}>添加選項</Button>
          </Form.Item>
        </>
      )}
    </Form.List>
  </Form>
}

此時頁面如下
React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片,前端問題及案例,react.js,javascript,前端,canvas
上述代碼中有個坑

  • 因為產(chǎn)品要求,需要給個初始化數(shù)據(jù),并且文字要在圖片內(nèi)水平垂直居中。但是初始化數(shù)據(jù)時是無法獲取到圖片的寬高的,并且初始化時在useEffect中也無法通過ref獲取圖片的大小,此時只能將接收到的圖片生成新的圖片,然后讀取新圖片的寬高賦值給ImageSize,此時方可獲取到圖片真正的寬高,然后再傳遞給ParamsOptionComp組件

    MaterialEditComp.jsx

    const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
    
    useEffect(() => {
        const img = new Image();
        img.src = imgSrc
    
        img.onload = () => {
          setImageSize({ width: img.width, height: img.height });
    	};
    }, []);
    <ParamsOptionComp onValuesChange={onValuesChange} imageSize={imageSize} removeNode=		 {removeNode} />
    

    ParamsOptionComp.jsx

    下方初始化第一條數(shù)據(jù)時,因為initialValue就是所謂的defaultValue,只會在第一次賦值的時候改變,無法直接設(shè)置initialValue的值來改變,所以獲取到的也是第一次初始化的寬高都為0,但是我們 可以通過Form的resetFields()方法來解決這個問題,當(dāng)監(jiān)聽到imageSize發(fā)生變化時我們可以調(diào)用resetFields()來重新設(shè)置initialValue的值。
    React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片,前端問題及案例,react.js,javascript,前端,canvas

    useEffect(() => {
      form.resetFields()
    }, [imageSize])
    
3. 初始化新增第一個節(jié)點到頁面中的某個指定模塊

此時輸入框中已經(jīng)有值了,但是此處圖片中還沒有初始化值,此時,需要在useEffect中調(diào)用AddNode初始化第一個節(jié)點的值。

const AddNode = ({ content, color, size, left, top }, index) => {
    const contentNode = contentRef.current;
    let newNode = document.createElement('div');
    newNode.className = 'node' + index;
    // 此處判斷節(jié)點是否已經(jīng)存在
    const bool = contentNode?.childNodes[index]
    if (bool) {
      newNode = contentNode.childNodes[index]
    }

    newNode.textContent = content
    newNode.style.color = color;
    newNode.style.fontSize = size + 'px';
    newNode.style.top = top + 'px';
    newNode.style.left = left + 'px';
    newNode.style.position = 'absolute';

    // 節(jié)點不存在新增階段
    if (!bool) {
      contentNode.appendChild(newNode);
    } else {
      // 節(jié)點存在則替換原來的節(jié)點
      contentNode.replaceChild(newNode, contentNode.childNodes[index])
    }
  }
  
   useEffect(() => {
    const img = new Image();
    img.src = imgSrc

    img.onload = () => {
      setImageSize({ width: img.width, height: img.height });
      AddNode({
        content: '文字內(nèi)容',
        color: '#000000',
        size: 24,
        left: img.width / 2 - 48,
        top: img.height / 2 - 24
      }, 0);
    };
  }, []);
4. 當(dāng)文本框發(fā)生變動,修改節(jié)點信息

當(dāng)文本框發(fā)生變動通過表單的onValuesChange 進(jìn)行監(jiān)聽,遍歷表單中的數(shù)據(jù)新增節(jié)點信息

const onValuesChange = (changedValues, allValues) => {
    // index標(biāo)記當(dāng)前是第幾個節(jié)點
    allValues.paramAttribute.forEach((item, index) => {
      item && AddNode(item, index)
    })
  }
5. 實現(xiàn)節(jié)點刪除

當(dāng)進(jìn)行節(jié)點刪除時,調(diào)用傳遞給ParamsOptionComp組件的removeNode方法獲取到刪除的節(jié)點

  //  刪除節(jié)點
  const removeNode = (index) => {
    const contentNode = contentRef.current;
    const bool = contentNode?.childNodes[index]
    if (bool) {
      contentNode.removeChild(contentNode.childNodes[index])
    }
  }
6. 利用html2canvas將模塊生成canvas,然后轉(zhuǎn)化成圖片

此時需要利用html2canvas將模塊生成canvas,然后轉(zhuǎn)化成圖片,如果需要調(diào)用接口將圖片保存下來,此處還需將圖片轉(zhuǎn)換成二進(jìn)制,如果不需要則直接下載就好

  // 將圖片轉(zhuǎn)換成二進(jìn)制形式
  const base64ToBlob = (code) => {
    let parts = code.split(';base64,')
    let contentType = parts[0].split(':')[1]
    let raw = window.atob(parts[1])
    let rawLength = raw.length
    let uint8Array = new Uint8Array(rawLength)
    for (let i = 0; i < rawLength; i++) {
      uint8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uint8Array], { type: contentType })
  }

  // 保存圖片
  const saveImage = async () => {
    const contentNode = contentRef.current;
    const canvas = await html2canvas(contentNode, {
      useCORS: true,
      allowTaint: true,//允許污染
      backgroundColor: '#ffffff',
      // toDataURL: src
    })

    const imgData = canvas.toDataURL('image/png');
    let blob = base64ToBlob(imgData)
    const link = document.createElement('a');
    link.href = imgData;
    // link.href = URL.createObjectURL(blob);
    getNewImage(link.href)
    // console.log(blob, 11)
    link.download = 'page-image.' + blob.type.split('/')[1];
    link.click();
  }

注意:此處使用html2canvas時, 必須配置以下信息,否則圖片信息無法進(jìn)行轉(zhuǎn)換

{
      useCORS: true,
      allowTaint: true,//允許污染
      backgroundColor: '#ffffff',
      // toDataURL: src
    }

完整代碼

MaterialEditComp.jsx

import React, { useEffect, useRef, useState } from 'react'
import { Button } from 'antd'
import ParamsOptionComp from './ParamsOptionComp'
import html2canvas from 'html2canvas';
import './index.less'

export default function MaterialEditComp(props) {
  const { src, getNewImage } = props;
  const [imgSrc, setImgSrc] = React.useState(src);
  const contentRef = useRef(null);
  const [imageSize, setImageSize] = useState({ width: 0, height: 0 });

/* 
  const divStyle = {
    background: `url(${imgSrc}) no-repeat`,
    backgroundSize: 'cover',
    backgroundPosition: 'center',
    width: imageSize.width + 'px',
    height: imageSize.height + 'px',
    marginBottom: '30px'
  }; */

  const onValuesChange = (changedValues, allValues) => {
    // console.log(changedValues, allValues, 11)
    allValues.paramAttribute.forEach((item, index) => {
      item && AddNode(item, index)
    })
  }

  // 新增節(jié)點
  const AddNode = ({ content, color, size, left, top }, index) => {
    const contentNode = contentRef.current;
    let newNode = document.createElement('div');
    newNode.className = 'node' + index;
    // 此處判斷節(jié)點是否已經(jīng)存在
    const bool = contentNode?.childNodes[index]
    if (bool) {
      newNode = contentNode.childNodes[index]
    }

    newNode.textContent = content
    newNode.style.color = color;
    newNode.style.fontSize = size + 'px';
    newNode.style.top = top + 'px';
    newNode.style.left = left + 'px';
    newNode.style.position = 'absolute';

    // 節(jié)點不存在新增階段
    if (!bool) {
      contentNode.appendChild(newNode);
    } else {
      // 節(jié)點存在則替換原來的節(jié)點
      contentNode.replaceChild(newNode, contentNode.childNodes[index])
    }
  }

  //  刪除節(jié)點
  const removeNode = (index) => {
    const contentNode = contentRef.current;
    const bool = contentNode?.childNodes[index]
    if (bool) {
      contentNode.removeChild(contentNode.childNodes[index])
    }
  }
  // 將圖片轉(zhuǎn)換成二進(jìn)制形式
  const base64ToBlob = (code) => {
    let parts = code.split(';base64,')
    let contentType = parts[0].split(':')[1]
    let raw = window.atob(parts[1])
    let rawLength = raw.length
    let uint8Array = new Uint8Array(rawLength)
    for (let i = 0; i < rawLength; i++) {
      uint8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uint8Array], { type: contentType })
  }

  // 保存圖片
  const saveImage = async () => {
    const contentNode = contentRef.current;
    const canvas = await html2canvas(contentNode, {
      useCORS: true,
      allowTaint: true,//允許污染
      backgroundColor: '#ffffff',
      // toDataURL: src
    })

    const imgData = canvas.toDataURL('image/png');
    let blob = base64ToBlob(imgData)
    const link = document.createElement('a');
    link.href = imgData;
    // link.href = URL.createObjectURL(blob);
    getNewImage(link.href)
    // console.log(blob, 11)
    link.download = 'page-image.' + blob.type.split('/')[1];
    link.click();
  }


  useEffect(() => {
    const img = new Image();
    img.src = imgSrc

    img.onload = () => {
      setImageSize({ width: img.width, height: img.height });
      AddNode({
        content: '文字內(nèi)容',
        color: '#000000',
        size: 24,
        left: img.width / 2 - 48,
        top: img.height / 2 - 24
      }, 0);
    };
  }, []);


  return (
    <>
      <div ref={contentRef} style={{
        background: `url(${imgSrc}) no-repeat`,
        backgroundSize: 'cover',
        backgroundPosition: 'center',
        width: imageSize.width + 'px',
        height: imageSize.height + 'px',
        marginBottom: '30px'
      }} className="content">

      </div>
      <ParamsOptionComp onValuesChange={onValuesChange} imageSize={imageSize} removeNode={removeNode} />
      <Button type="primary" htmlType="submit" onClick={saveImage} className='btn'>
        生成新的圖片
      </Button>
    </>
  )
}

ParamsOptionComp.jsx

import React, { useEffect, useState } from 'react'
import { Input, Form, Space, Button, InputNumber } from 'antd'
import { PlusOutlined, MinusCircleOutlined, DragOutlined } from '@ant-design/icons'

export default function ParamsOptionComp(props) {
  const { onValuesChange, imageSize, removeNode } = props
  const [count, setCount] = useState(0)
  const [form] = Form.useForm();

  // 坑
  useEffect(() => {
    form.resetFields()
  }, [imageSize])


  return <Form form={form} name="dynamic_form_nest_item"
    // 坑
    initialValues={{
      paramAttribute: [{
        left: imageSize.width / 2 - 48,
        top: imageSize.height / 2 - 24,
        content: '文字內(nèi)容'
      }]
    }}
    onValuesChange={onValuesChange} >

    <Form.List name="paramAttribute">
      {(fields, { add, remove, move }) => (
        <>
          {fields.map(({ key, name, ...restField }, index) => (
            <Space key={key} style={{ display: 'flex', marginBottom: 0 }} align="baseline">
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'content']}
                label="文字內(nèi)容"
                rules={[{ required: true, message: '請輸入文字內(nèi)容' }]}
              >
                <Input placeholder="文字內(nèi)容" maxLength={50} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'color']}
                label="文字顏色"
                rules={[{ required: true, message: '請輸入文字顏色' }]}
                initialValue="#000000"
              >
                <Input placeholder="文字顏色" type="color" style={{ width: '80px' }} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'size']}
                label="文字大小"
                rules={[{ required: true, message: '請輸入文字大小' }]}
                initialValue="24"
              >
                <InputNumber placeholder="文字大小" min={12} value={13} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'top']}
                label="上邊距"
                rules={[{ required: true, message: '請輸入上邊距' }]}
                initialValue={imageSize.height / 2 - 24}
              >
                <InputNumber placeholder="上邊距" value={13} />
              </Form.Item>
              <Form.Item
                style={{ marginBottom: '10px' }}
                {...restField}
                name={[name, 'left']}
                label="左邊距"
                rules={[{ required: true, message: '請輸入左邊距' }]}
                initialValue={imageSize.width / 2 - 48}
              >
                <InputNumber placeholder="左邊距" value={13} />
              </Form.Item>
              <MinusCircleOutlined onClick={() => {
                if (count === 0) {
                  return
                }
                remove(name)
                removeNode(index)
                setCount(count => count - 1);
              }} />
            </Space>
          ))}
          <Form.Item>
            <Button type="dashed" onClick={async () => {
              try {
                const values = await form.validateFields()
                add();
                setCount(count => count + 1);
              } catch (errorInfo) {
                return;
              }
            }} block icon={<PlusOutlined />}>添加選項</Button>
          </Form.Item>
        </>
      )}
    </Form.List>
  </Form>
}

使用:文章來源地址http://www.zghlxwxcb.cn/news/detail-739739.html

const src=''
const getNewImage = (image) => {
    console.log(image)
    page.close()
 }
return <MaterialEditComp src={src}  getNewImage={getNewImage} />

到了這里,關(guān)于React實現(xiàn)文本框輸入文字內(nèi)容動態(tài)給圖片添加文字信息(多個)并生成新的圖片的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 怎么在PDF添加文本框?6種快速向PDF添加文字教程

    怎么在PDF添加文本框?6種快速向PDF添加文字教程

    有時您可能希望填寫表格或在 PDF 文件中留下評論。這需要您將文本框和文本添加到 PDF。文本框是一個文本字段,您可以在其中鍵入文本。但是,除非您使用專用的 PDF 編輯器,否則編輯 PDF 文件具有挑戰(zhàn)性。了解正確的 PDF 工具和將文本框添加到 PDF的簡單方法可以幫助您高效

    2024年01月23日
    瀏覽(18)
  • tinymce4/5實現(xiàn)將word中內(nèi)容(文字圖片等)直接粘貼至編輯器中——利用插件tinymce-powerpaste-plugin

    tinymce4/5實現(xiàn)將word中內(nèi)容(文字圖片等)直接粘貼至編輯器中——利用插件tinymce-powerpaste-plugin

    TinyMCE是一款易用、且功能強大的所見即所得的富文本編輯器。同類程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。 TinyMCE的優(yōu)勢: 開源可商用,基于LGPL2.1 插件豐富,自帶插件基本涵蓋日常所需功能(示例看下面的Demo-2) 接口豐富,可擴展性強,有

    2024年02月15日
    瀏覽(29)
  • React Native 文本輸入基礎(chǔ)知識

    在 React Native 中提供了一個文本輸入組件 TextInput 。此組件主要是監(jiān)聽鍵盤輸入事件,并把對應(yīng)的輸入值顯示在組件中,此組件還提供了很多功能配置參數(shù),例如自動更正、自動大寫、占位符文本和不同的鍵盤類型(例如數(shù)字鍵盤)。 我們首先來編寫一個簡單的實例,使用

    2024年02月12日
    瀏覽(23)
  • React Native文本添加下劃線

    React Native文本添加下劃線

    2024年02月13日
    瀏覽(25)
  • Qt圖片編輯 - 在直線添加文字

    Qt圖片編輯 - 在直線添加文字

    在繪制一條直線時,比如說在直線中間輸出文字,如下圖所示 本質(zhì)上不難,定位到位置,然后drawText就可以了 難就難在 文字要跟隨線的斜率,例如 ? ?還有,文字最好保證在線的“上方” 首先是角度問題 這個角度跟線Line與X軸夾角是一致的,因此,只要有線兩端坐標(biāo)就可以

    2024年02月15日
    瀏覽(25)
  • Python代碼學(xué)習(xí)之給圖片添加文字或圖片水印

    Python代碼學(xué)習(xí)之給圖片添加文字或圖片水印

    圖片加水印有什么好處?在現(xiàn)今的數(shù)字化時代,網(wǎng)絡(luò)上的圖片泛濫,盜圖現(xiàn)象也越來越嚴(yán)重。因此,在發(fā)布文章時,為了保護(hù)自己的原創(chuàng)作品版權(quán),很多人選擇使用水印來保護(hù)他們的圖片。這樣就能更好地做到: 1.版權(quán)保護(hù):在商業(yè)用途的照片中添加水印可以幫助保護(hù)作者的

    2024年02月09日
    瀏覽(20)
  • textarea文本框根據(jù)輸入內(nèi)容自動適應(yīng)高度

    第一種: 第二種: 加一個監(jiān)聽該文本框內(nèi)容變化的方法? oninput ,然后在該方法里手動計算文本框的高度并實現(xiàn)自適應(yīng):

    2024年01月21日
    瀏覽(44)
  • React Native從文本內(nèi)容尾部截取顯示省略號

    React Native從文本內(nèi)容尾部截取顯示省略號

    參考鏈接: https://www.reactnative.cn/docs/text#ellipsizemode https://chat.xutongbao.top/

    2024年02月14日
    瀏覽(33)
  • jQuery 在圖片和文字中插入內(nèi)容(多種情況考慮)

    jQuery 在圖片和文字中插入內(nèi)容(多種情況考慮)

    昨天接到一個新的需要,在后臺文章編輯器中,每一個文章的正文前面,可以單獨添加一個電頭字段,但是如果在富文本編輯器中最上面就添加圖片的話,圖片就會把電頭和正文中的文字給隔開。需要做的是獲取到電頭字段,然后在正文中的文字部分的最前面插入電頭字段。

    2023年04月25日
    瀏覽(19)
  • Vue+element-ui的el-cascader實現(xiàn)動態(tài)添加刪除級聯(lián)地點輸入框

    實現(xiàn)省市區(qū)三級地點級聯(lián)選擇,可聯(lián)想; 包括始發(fā)地點、途徑地點、終止地點,始發(fā)地點、終止地點均為一個,途徑地點可以沒有也可以是多個; 用戶可以動態(tài)添加/刪除途徑地點。 使用級聯(lián)選擇器Cascader需要的樹形數(shù)據(jù),前端請求到后端獲取省市區(qū)數(shù)據(jù)并處理為elementui官網(wǎng)

    2024年02月04日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包