Генератор изображений по описанию - 7Post
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ИИ-чат + рисовалка</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f0f4f8;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 20px;
}
.chat-container {
max-width: 700px;
width: 100%;
background: white;
border-radius: 24px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
height: 80vh;
max-height: 700px;
}
.chat-header {
background: #1a1a2e;
color: #fff;
padding: 18px 24px;
font-size: 1.2rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.chat-header span {
background: #e94560;
border-radius: 50%;
width: 12px;
height: 12px;
display: inline-block;
}
.chat-messages {
flex: 1;
padding: 20px 24px;
overflow-y: auto;
background: #fafbfc;
display: flex;
flex-direction: column;
gap: 12px;
}
.message {
padding: 12px 16px;
border-radius: 18px;
max-width: 80%;
word-wrap: break-word;
line-height: 1.5;
animation: fadeIn 0.3s ease;
}
.message.user {
align-self: flex-end;
background: #1a1a2e;
color: white;
border-bottom-right-radius: 4px;
}
.message.bot {
align-self: flex-start;
background: #e9eef2;
color: #1a1a2e;
border-bottom-left-radius: 4px;
}
.message img {
max-width: 100%;
border-radius: 12px;
margin-top: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.message .image-prompt {
font-size: 0.9rem;
color: #555;
margin-top: 4px;
font-style: italic;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
.typing {
align-self: flex-start;
background: #e9eef2;
padding: 12px 16px;
border-radius: 18px;
border-bottom-left-radius: 4px;
color: #555;
font-style: italic;
display: inline-block;
}
.typing::after {
content: '...';
animation: dots 1.2s steps(3, end) infinite;
}
@keyframes dots {
0% { content: ''; }
33% { content: '.'; }
66% { content: '..'; }
100% { content: '...'; }
}
.chat-input-area {
display: flex;
padding: 16px 24px;
background: white;
border-top: 1px solid #e2e8f0;
gap: 10px;
align-items: center;
}
.chat-input-area input {
flex: 1;
padding: 12px 16px;
border: 1px solid #d1d9e6;
border-radius: 30px;
font-size: 1rem;
outline: none;
transition: border 0.2s;
}
.chat-input-area input:focus {
border-color: #1a1a2e;
}
.chat-input-area button {
background: #1a1a2e;
color: white;
border: none;
padding: 12px 24px;
border-radius: 30px;
font-size: 1rem;
cursor: pointer;
transition: background 0.2s;
white-space: nowrap;
}
.chat-input-area button:hover {
background: #e94560;
}
.chat-input-area button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.info {
font-size: 0.8rem;
color: #888;
text-align: center;
padding: 6px;
background: #f8fafc;
}
.info a {
color: #1a1a2e;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<span></span> ИИ-чат · текст + картинки
</div>
<div class="chat-messages" id="chatMessages">
<div class="message bot">👋 Привет! Я умею отвечать на вопросы и рисовать по описанию. Просто напиши «нарисуй ...» или «сгенерируй ...»</div>
</div>
<div class="chat-input-area">
<input type="text" id="userInput" placeholder="Спроси что-нибудь или попроси нарисовать..." autofocus>
<button id="sendBtn">Отправить</button>
</div>
<div class="info">
Используется <a href="https://pollinations.ai" target="_blank">Pollinations.ai</a> (бесплатно, без ключей)
</div>
</div>
<script>
(function() {
const messagesContainer = document.getElementById('chatMessages');
const userInput = document.getElementById('userInput');
const sendBtn = document.getElementById('sendBtn');
// История диалога (для контекста)
let conversationHistory = [];
// Функция добавления сообщения в чат
function addMessage(text, sender, imageUrl = null, promptText = null) {
const div = document.createElement('div');
div.className = `message ${sender}`;
if (imageUrl) {
// Сообщение-картинка
const img = document.createElement('img');
img.src = imageUrl;
img.alt = 'Сгенерированное изображение';
div.appendChild(img);
if (promptText) {
const caption = document.createElement('div');
caption.className = 'image-prompt';
caption.textContent = `🖼 «${promptText}»`;
div.appendChild(caption);
}
// Добавляем и текстовое пояснение, если есть
if (text) {
const textNode = document.createElement('div');
textNode.textContent = text;
div.prepend(textNode);
}
} else {
div.textContent = text;
}
messagesContainer.appendChild(div);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// Показать индикатор печати
function showTyping() {
const typingDiv = document.createElement('div');
typingDiv.className = 'typing';
typingDiv.id = 'typingIndicator';
typingDiv.textContent = 'ИИ думает';
messagesContainer.appendChild(typingDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
function hideTyping() {
const el = document.getElementById('typingIndicator');
if (el) el.remove();
}
// Проверка, является ли запрос на генерацию картинки
function isImageRequest(text) {
const triggers = ['нарисуй', 'сгенерируй', 'покажи', 'нарисуй мне', 'создай'];
const lower = text.toLowerCase().trim();
for (let trigger of triggers) {
if (lower.startsWith(trigger) || lower.includes(trigger)) {
return true;
}
}
return false;
}
// Извлечение промпта для картинки (убираем команду)
function extractPrompt(text) {
const triggers = ['нарисуй', 'сгенерируй', 'покажи', 'нарисуй мне', 'создай'];
let prompt = text;
for (let trigger of triggers) {
if (prompt.toLowerCase().startsWith(trigger)) {
prompt = prompt.slice(trigger.length).trim();
break;
}
// Ищем внутри
const idx = prompt.toLowerCase().indexOf(trigger);
if (idx !== -1) {
prompt = prompt.slice(idx + trigger.length).trim();
break;
}
}
// Если осталось пусто, ставим дефолт
if (!prompt) prompt = 'красивое абстрактное искусство';
return prompt;
}
// Генерация картинки через Pollinations (GET-запрос)
function generateImage(prompt) {
// Кодируем промпт для URL
const encoded = encodeURIComponent(prompt);
// Используем параметр width=512&height=512, можно изменить
const url = `https://image.pollinations.ai/prompt/${encoded}?width=512&height=512&nologo=true`;
return url; // Просто возвращаем URL, т.к. это GET-запрос, изображение отдаётся сразу
}
// Получение текстового ответа от ИИ (Pollinations text API)
async function getTextResponse(userMessage, history) {
// Строим историю для контекста (последние 5 сообщений)
const context = history.slice(-5).map(msg => `${msg.role}: ${msg.content}`).join('\n');
const fullPrompt = `${context}\nПользователь: ${userMessage}\nАссистент:`;
try {
const response = await fetch('https://text.pollinations.ai/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [
{ role: 'system', content: 'Ты полезный и дружелюбный ассистент, отвечаешь на русском языке.' },
...history.map(msg => ({ role: msg.role, content: msg.content })),
{ role: 'user', content: userMessage }
],
model: 'openai',
seed: Math.floor(Math.random() * 1000000),
temperature: 0.7
})
});
if (!response.ok) throw new Error(`HTTP error ${response.status}`);
const data = await response.json();
// Ответ может быть в поле choices[0].message.content или напрямую текст
let reply = '';
if (data.choices && data.choices.length > 0) {
reply = data.choices[0].message.content;
} else if (data.message) {
reply = data.message.content;
} else if (typeof data === 'string') {
reply = data;
} else {
reply = 'Извините, не удалось получить ответ.';
}
return reply.trim();
} catch (error) {
console.error('Ошибка при запросе к текстовому API:', error);
return 'Произошла ошибка при обращении к ИИ. Попробуйте позже.';
}
}
// Основная функция отправки сообщения
async function sendMessage() {
const userMessage = userInput.value.trim();
if (!userMessage) return;
// Отключаем кнопку и инпут на время обработки
sendBtn.disabled = true;
userInput.disabled = true;
// Добавляем сообщение пользователя в чат и историю
addMessage(userMessage, 'user');
conversationHistory.push({ role: 'user', content: userMessage });
// Проверяем, является ли запрос на генерацию картинки
if (isImageRequest(userMessage)) {
const prompt = extractPrompt(userMessage);
// Показываем индикатор загрузки
showTyping();
// Имитация задержки (можно убрать)
await new Promise(resolve => setTimeout(resolve, 800));
hideTyping();
// Генерируем URL картинки
const imageUrl = generateImage(prompt);
// Отображаем картинку в чате
addMessage('', 'bot', imageUrl, prompt);
// Сохраняем в истории (как ответ бота)
conversationHistory.push({ role: 'assistant', content: `[Изображение: ${prompt}]` });
} else {
// Обычный текстовый запрос
showTyping();
let botReply = await getTextResponse(userMessage, conversationHistory);
hideTyping();
// Если ответ пустой, даём заглушку
if (!botReply) botReply = 'Не удалось сформулировать ответ.';
addMessage(botReply, 'bot');
conversationHistory.push({ role: 'assistant', content: botReply });
}
// Очищаем поле и включаем обратно
userInput.value = '';
sendBtn.disabled = false;
userInput.disabled = false;
userInput.focus();
}
// Обработчики событий
sendBtn.addEventListener('click', sendMessage);
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
sendMessage();
}
});
// Автофокус
userInput.focus();
})();
</script>
</body>
</html>Сервис полностью бесплатный и не требует регистрации, что идеально подходит для публичного блога
✨ Возможности
- 🎯 5 размеров изображения (1:1, 16:9, 9:16, 4:3, 3:4)
- 🤖 5 моделей (Flux для качества, Turbo для скорости, Anime, 3D, Realism)
- 🌱 Seed — позволяет воспроизводить одинаковые результаты
- 💡 Готовые примеры — клик по чипу вставляет текст
- ⬇️ Кнопка скачивания результата
- 📱 Адаптивный дизайн — работает на телефонах
- ⌨️ Ctrl+Enter для быстрой генерации